From 629ecac15279fffa15ee1d5b815aa88492e52e8e Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Mon, 8 Aug 2022 20:27:23 -0400 Subject: [PATCH 01/74] fix build --- build.gradle.kts | 11 ++++++----- buildSrc/src/main/kotlin/Dependencies.kt | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 24ded7a6..fb72e0cc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,6 +9,7 @@ buildscript { repositories { google() mavenCentral() + gradlePluginPortal() maven(url = "https://maven.pkg.jetbrains.space/public/p/compose/dev") maven(url = "https://dl.bintray.com/kotlin/dokka") maven(url = "https://kotlin.bintray.com/ktor") @@ -113,8 +114,8 @@ allprojects { url = if (version.toString().endsWith("SNAPSHOT")) uri(snapshotsRepoUrl) else uri(releasesRepoUrl) credentials { - username = rootProject.ext["ossrh.username"] as String - password = rootProject.ext["ossrh.password"] as String + username = rootProject.ext["ossrh.username"] as String? ?: "" + password = rootProject.ext["ossrh.password"] as String? ?: "" } } @@ -134,7 +135,7 @@ allprojects { nexusStaging { packageGroup = Kamel.Group - stagingProfileId = rootProject.ext["stagingProfileId"] as String - username = rootProject.ext["ossrh.username"] as String - password = rootProject.ext["ossrh.password"] as String + stagingProfileId = rootProject.ext["stagingProfileId"] as String? ?: "" + username = rootProject.ext["ossrh.username"] as String? ?: "" + password = rootProject.ext["ossrh.password"] as String? ?: "" } diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 357f8428..183189d3 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -33,7 +33,7 @@ private object Versions { const val Ktor = "2.0.3" const val Coroutines = "1.6.3" const val Compose = "1.2.0-alpha01-dev753" - const val AGP = "7.2.1" + const val AGP = "7.0.4" object Android { const val Appcompat = "1.4.2" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1565a526..1d8896d0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sun Jul 10 06:06:14 TRT 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME \ No newline at end of file From d01f281d3b70907418eecd2986c25d551da8825b Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Tue, 9 Aug 2022 01:31:17 -0400 Subject: [PATCH 02/74] Update kotlin to 1.7.10 and other dependencies. Cleanup unused --- build.gradle.kts | 2 +- buildSrc/build.gradle.kts | 2 +- buildSrc/src/main/kotlin/Dependencies.kt | 16 ++++++---------- buildSrc/src/main/kotlin/Plugins.kt | 6 +++--- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index fb72e0cc..480a5d1a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -127,7 +127,7 @@ allprojects { tasks.withType { kotlinOptions { - freeCompilerArgs = listOf("-Xallow-result-return-type", "-Xopt-in=kotlin.RequiresOptIn") + freeCompilerArgs = listOf("-Xallow-result-return-type") } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 445e21f7..f1552441 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,5 +1,5 @@ repositories { - jcenter() + mavenCentral() } plugins { diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 183189d3..f6d02214 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -5,8 +5,6 @@ object Dependencies { const val KotlinReflect = "org.jetbrains.kotlin:kotlin-reflect:${Versions.Kotlin}" object Android { - const val Appcompat = "androidx.appcompat:appcompat:${Versions.Android.Appcompat}" - const val Core = "androidx.core:core-ktx:${Versions.Android.Core}" const val ActivityCompose = "androidx.activity:activity-compose:${Versions.Android.ActivityCompose}" const val GradlePlugin = "com.android.tools.build:gradle:${Versions.AGP}" const val Material = "com.google.android.material:material:${Versions.Android.Material}" @@ -27,18 +25,16 @@ object Dependencies { } -private object Versions { +object Versions { - const val Kotlin = "1.7.0" + const val Kotlin = "1.7.10" const val Ktor = "2.0.3" - const val Coroutines = "1.6.3" - const val Compose = "1.2.0-alpha01-dev753" - const val AGP = "7.0.4" + const val Coroutines = "1.6.4" + const val Compose = "1.2.0-alpha01-dev745" + const val AGP = "7.2.2" object Android { - const val Appcompat = "1.4.2" - const val Core = "1.8.0" - const val ActivityCompose = "1.5.0" + const val ActivityCompose = "1.5.1" const val Material = "1.6.1" } diff --git a/buildSrc/src/main/kotlin/Plugins.kt b/buildSrc/src/main/kotlin/Plugins.kt index 5e9b8fdb..5b7220a1 100644 --- a/buildSrc/src/main/kotlin/Plugins.kt +++ b/buildSrc/src/main/kotlin/Plugins.kt @@ -9,12 +9,12 @@ inline val PluginDependenciesSpec.compose: PluginDependencySpec inline val PluginDependenciesSpec.multiplatform: PluginDependencySpec get() = kotlin("multiplatform") +inline val PluginDependenciesSpec.mokoResources: PluginDependencySpec + get() = id("dev.icerock.mobile.multiplatform-resources") version Versions.MokoResources + inline val PluginDependenciesSpec.`nexus-staging`: PluginDependencySpec get() = id("io.codearte.nexus-staging") version "0.22.0" -inline val PluginDependenciesSpec.dokka: PluginDependencySpec - get() = id("org.jetbrains.dokka") version "1.4.20" - inline val PluginDependenciesSpec.`android-library`: PluginDependencySpec get() = id("com.android.library") From 43f9daee7ab728612d796b1b68d2da3873251a99 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Tue, 9 Aug 2022 02:00:22 -0400 Subject: [PATCH 03/74] setup project for native darwin targets. Use moko-resources to load common resources --- buildSrc/src/main/kotlin/Dependencies.kt | 2 + buildSrc/src/main/kotlin/Targets.kt | 14 ++ gradle.properties | 5 + kamel-core/build.gradle.kts | 70 ++++++-- .../io/kamel/core/fetcher/FileFetcher.kt | 39 +++++ .../kotlin/io/kamel/core/mapper/Mappers.kt | 9 + .../kotlin/io/kamel/core/utils/ConfigUtils.kt | 50 ++++++ .../kotlin/io/kamel/core/utils/Platform.kt | 16 ++ .../io/kamel/core/fetcher/HttpFetcherTest.kt | 72 ++++++++ .../io/kamel/core/utils/MappersUtils.kt | 8 + .../kotlin/io/kamel/core/utils/JvmPlatform.kt | 2 +- .../kotlin/io/kamel/core/cache/LruCache.kt | 26 +++ .../io/kamel/core/cache/common/LruCache.kt | 161 ++++++++++++++++++ kamel-image/build.gradle.kts | 69 +++++--- .../image/fetcher/ResourcesFetcherTest.kt | 12 +- .../io/kamel/image/config/KamelConfig.kt | 15 ++ .../kamel/image/decoder/ImageBitmapDecoder.kt | 19 +++ .../kamel/image/decoder/ImageVectorDecoder.kt | 17 ++ .../io/kamel/image/decoder/SvgDecoder.kt | 17 ++ .../kamel/image/fetcher/ResourcesFetcher.kt | 32 ++++ kamel-samples/build.gradle.kts | 49 +++--- .../io/kamel/samples/ResourcesSample.kt | 1 - .../kotlin/io/kamel/samples/Gallery.kt | 9 +- .../io/kamel/samples/ResourcesSample.kt | 2 +- .../kotlin/io/kamel/samples/SvgSample.kt | 2 +- kamel-tests/build.gradle.kts | 35 +++- .../resources/{ => MR/files}/Compose.png | Bin .../resources/{ => MR/files}/Kotlin.svg | 0 .../kotlin/io/kamel/tests/JvmTestUtils.kt | 17 ++ .../kotlin/io/kamel/tests/JvmTestUtils.kt | 6 +- 30 files changed, 693 insertions(+), 83 deletions(-) create mode 100644 buildSrc/src/main/kotlin/Targets.kt create mode 100644 kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt create mode 100644 kamel-core/src/darwinMain/kotlin/io/kamel/core/mapper/Mappers.kt create mode 100644 kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/ConfigUtils.kt create mode 100644 kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt create mode 100644 kamel-core/src/darwinTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt create mode 100644 kamel-core/src/darwinTest/kotlin/io/kamel/core/utils/MappersUtils.kt create mode 100644 kamel-core/src/nonJvmMain/kotlin/io/kamel/core/cache/LruCache.kt create mode 100644 kamel-core/src/nonJvmMain/kotlin/io/kamel/core/cache/common/LruCache.kt create mode 100644 kamel-image/src/nonJvmMain/kotlin/io/kamel/image/config/KamelConfig.kt create mode 100644 kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt create mode 100644 kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt create mode 100644 kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt create mode 100644 kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt rename kamel-tests/src/commonMain/resources/{ => MR/files}/Compose.png (100%) rename kamel-tests/src/commonMain/resources/{ => MR/files}/Kotlin.svg (100%) create mode 100644 kamel-tests/src/darwinMain/kotlin/io/kamel/tests/JvmTestUtils.kt diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index f6d02214..d146fdee 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -21,6 +21,7 @@ object Dependencies { const val Ktor = "io.ktor:ktor-client-mock:${Versions.Ktor}" const val Coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.Coroutines}" const val Compose = "org.jetbrains.compose.ui:ui-test-junit4:${Versions.Compose}" + const val MokoResources = "dev.icerock.moko:resources:${Versions.MokoResources}" } } @@ -32,6 +33,7 @@ object Versions { const val Coroutines = "1.6.4" const val Compose = "1.2.0-alpha01-dev745" const val AGP = "7.2.2" + const val MokoResources = "0.20.1" object Android { const val ActivityCompose = "1.5.1" diff --git a/buildSrc/src/main/kotlin/Targets.kt b/buildSrc/src/main/kotlin/Targets.kt new file mode 100644 index 00000000..4599a58c --- /dev/null +++ b/buildSrc/src/main/kotlin/Targets.kt @@ -0,0 +1,14 @@ +object Targets { + + val iosTargets = arrayOf( + "iosArm64", "iosX64", + ) + val macosTargets = arrayOf( + "macosX64", "macosArm64", + ) + val darwinTargets = iosTargets + macosTargets + val linuxTargets = arrayOf() + val mingwTargets = arrayOf() + val nativeTargets = linuxTargets + darwinTargets + mingwTargets + +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index b8822f8b..00afec92 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,8 @@ +org.gradle.jvmargs=-Xmx3g kotlin.code.style=official +kotlin.native.cacheKind=none +kotlin.native.useEmbeddableCompilerJar=true +kotlin.native.binary.memoryModel=experimental +compose.desktop.verbose=true android.useAndroidX=true kotlin.mpp.stability.nowarn=true \ No newline at end of file diff --git a/kamel-core/build.gradle.kts b/kamel-core/build.gradle.kts index b461c4d6..9e7e13ac 100644 --- a/kamel-core/build.gradle.kts +++ b/kamel-core/build.gradle.kts @@ -1,5 +1,6 @@ import org.jetbrains.compose.compose import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget plugins { multiplatform @@ -14,6 +15,37 @@ kotlin { jvm() + for (target in Targets.macosTargets) { + targets.add( + (presets.getByName(target).createTarget(target) as KotlinNativeTarget).apply { + binaries.forEach { + it.apply { + freeCompilerArgs += listOf( + "-linker-option", "-framework", "-linker-option", "Metal" + ) + } + } + } + ) + } + for (target in Targets.iosTargets) { + targets.add( + (presets.getByName(target).createTarget(target) as KotlinNativeTarget).apply { + binaries.forEach { + it.apply { + freeCompilerArgs += listOf( + "-linker-option", "-framework", "-linker-option", "Metal", + "-linker-option", "-framework", "-linker-option", "CoreText", + "-linker-option", "-framework", "-linker-option", "CoreGraphics" + ) + } + } + } + ) + } + + + sourceSets { val commonMain by getting { @@ -28,11 +60,9 @@ kotlin { val commonTest by getting { dependencies { implementation(project(":kamel-tests")) - implementation(kotlin("test-common")) - implementation(kotlin("test-annotations-common")) + implementation(kotlin("test")) implementation(Dependencies.Testing.Ktor) implementation(Dependencies.Testing.Coroutines) - implementation(Dependencies.Testing.Compose) } } @@ -43,8 +73,30 @@ kotlin { } val jvmTest by getting { - dependencies { - implementation(kotlin("test-junit")) + } + + val nonJvmMain by creating { + dependsOn(commonMain) + } + + val nonJvmTest by creating { + dependsOn(commonTest) + } + + val darwinMain by creating { + dependsOn(nonJvmMain) + } + + val darwinTest by creating { + dependsOn(nonJvmTest) + } + + Targets.darwinTargets.forEach { target -> + getByName("${target}Main") { + dependsOn(darwinMain) + } + getByName("${target}Test") { + dependsOn(darwinTest) } } @@ -54,13 +106,5 @@ kotlin { } } - targets.all { - compilations.all { - kotlinOptions { - freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn") - } - } - } - } } diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt new file mode 100644 index 00000000..1432b7df --- /dev/null +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt @@ -0,0 +1,39 @@ +package io.kamel.core.fetcher + +import io.kamel.core.DataSource +import io.kamel.core.Resource +import io.kamel.core.config.ResourceConfig +import io.kamel.core.utils.File +import io.ktor.utils.io.* +import kotlinx.cinterop.addressOf +import kotlinx.cinterop.usePinned +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import platform.Foundation.NSData +import platform.posix.memcpy + +/** + * Fetcher that fetchers [ByteReadChannel] from a file. + */ +internal actual object FileFetcher : Fetcher { + + override val source: DataSource = DataSource.Disk + + override val File.isSupported: Boolean + get() = true// exists() && isFile + + private fun NSData.toByteArray(): ByteArray = ByteArray(this@toByteArray.length.toInt()).apply { + usePinned { + memcpy(it.addressOf(0), this@toByteArray.bytes, this@toByteArray.length) + } + } + + override fun fetch( + data: File, + resourceConfig: ResourceConfig + ): Flow> = flow { + val bytes = ByteReadChannel(data.availableData.toByteArray()) + emit(Resource.Success(bytes, source)) + } + +} \ No newline at end of file diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/mapper/Mappers.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/mapper/Mappers.kt new file mode 100644 index 00000000..f1e0c8ec --- /dev/null +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/mapper/Mappers.kt @@ -0,0 +1,9 @@ +package io.kamel.core.mapper + +import io.kamel.core.utils.URI +import io.kamel.core.utils.URL +import io.ktor.http.* + +internal actual val URLMapper: Mapper = Mapper { URIMapper.map(it.absoluteString()!!) } + +internal actual val URIMapper: Mapper = Mapper { Url(it) } \ No newline at end of file diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/ConfigUtils.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/ConfigUtils.kt new file mode 100644 index 00000000..485f03d7 --- /dev/null +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/ConfigUtils.kt @@ -0,0 +1,50 @@ +@file:Suppress("UNCHECKED_CAST") + +package io.kamel.core.utils + +import io.kamel.core.config.KamelConfig +import io.kamel.core.decoder.Decoder +import io.kamel.core.fetcher.Fetcher +//import kotlin.reflect.full.createType +//import kotlin.reflect.full.isSubtypeOf +//import kotlin.reflect.full.isSupertypeOf +import kotlin.reflect.typeOf + +internal actual fun KamelConfig.findFetcherFor(data: T): Fetcher { + + val type = null //data::class.createType() + + val fetcher = null /*fetchers.findLast { fetcher -> + + val fetcherType = fetcher::class.supertypes + .firstOrNull() + ?.arguments + ?.firstOrNull() + ?.type ?: error("Unable to find type for $fetcher") + + val isSameType = fetcherType.isSupertypeOf(type) || fetcherType.isSubtypeOf(type) + + isSameType && with(fetcher) { data.isSupported } + }*/ + + checkNotNull(fetcher) { "Unable to find a fetcher for $type" } + + return fetcher as Fetcher +} + +@OptIn(ExperimentalStdlibApi::class) +internal actual inline fun KamelConfig.findDecoderFor(): Decoder { + + val type = typeOf>() + + val decoder = null /*decoders.findLast { decoder -> + + val decoderType = decoder::class.createType() + + decoderType.isSupertypeOf(type) || decoderType.isSubtypeOf(type) + }*/ + + checkNotNull(decoder) { "Unable to find a decoder for $type" } + + return decoder as Decoder +} diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt new file mode 100644 index 00000000..9de1e146 --- /dev/null +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt @@ -0,0 +1,16 @@ +package io.kamel.core.utils + +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import platform.Foundation.NSFileHandle +import platform.Foundation.NSURL + + +internal actual val Dispatchers.IO: CoroutineDispatcher get() = kotlinx.coroutines.Dispatchers.IO + +internal actual typealias File = NSFileHandle + +@Suppress("CONFLICTING_OVERLOADS") +internal actual typealias URL = NSURL + +internal actual typealias URI = String \ No newline at end of file diff --git a/kamel-core/src/darwinTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt b/kamel-core/src/darwinTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt new file mode 100644 index 00000000..e8a84541 --- /dev/null +++ b/kamel-core/src/darwinTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt @@ -0,0 +1,72 @@ +package io.kamel.core.fetcher + +import io.kamel.core.DataSource +import io.kamel.core.config.ResourceConfig +import io.kamel.core.config.ResourceConfigBuilder +import io.kamel.core.getOrNull +import io.kamel.core.isLoading +import io.kamel.core.map +import io.kamel.tests.HttpMockEngine +import io.ktor.client.* +import io.ktor.http.* +import io.ktor.util.* +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.test.runTest +import kotlin.test.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +@OptIn(ExperimentalCoroutinesApi::class) +class HttpFetcherTest { + + private val fetcher: HttpFetcher = HttpFetcher(HttpClient(HttpMockEngine)) + private val resourceConfig: ResourceConfig = ResourceConfigBuilder().build() + + @Test + fun testWebSocketUrlIsSupported() = runTest { + val urlBuilder = URLBuilder(protocol = URLProtocol.WS) + val isSupported = with(fetcher) { Url(urlBuilder).isSupported } + + assertFalse { isSupported } + } + + @Test + fun testHttpUrlIsSupported() = runTest { + val urlBuilder = URLBuilder(protocol = URLProtocol.HTTP) + val isSupported = with(fetcher) { Url(urlBuilder).isSupported } + + assertTrue { isSupported } + } + + @Test + fun testHttpsUrlIsSupported() = runTest { + val urlBuilder = URLBuilder(protocol = URLProtocol.HTTPS) + val isSupported = with(fetcher) { Url(urlBuilder).isSupported } + + assertTrue { isSupported } + } + + @Test + fun testFetchingEmptyImageBytes() = runTest { + val url = Url("/emptyImage.jpg") + val resource = fetcher.fetch(url, resourceConfig) + .first { !it.isLoading } + .map { it.toByteArray() } + + assertTrue { resource.getOrNull()!!.isEmpty() } + assertTrue { resource.source == DataSource.Network } + } + + @Test + fun testFetchingNonEmptyImageBytes() = runTest { + val url = Url("/image.svg") + val resource = fetcher.fetch(url, resourceConfig) + .first { !it.isLoading } + .map { it.toByteArray() } + + assertTrue { resource.getOrNull()!!.isNotEmpty() } + assertTrue { resource.source == DataSource.Network } + } + +} \ No newline at end of file diff --git a/kamel-core/src/darwinTest/kotlin/io/kamel/core/utils/MappersUtils.kt b/kamel-core/src/darwinTest/kotlin/io/kamel/core/utils/MappersUtils.kt new file mode 100644 index 00000000..9d382c6d --- /dev/null +++ b/kamel-core/src/darwinTest/kotlin/io/kamel/core/utils/MappersUtils.kt @@ -0,0 +1,8 @@ +package io.kamel.core.utils + +import platform.Foundation.NSURL + + +internal actual fun createURL(url: String): URL = NSURL.URLWithString(url)!! + +internal actual fun createURI(url: String): URI = url \ No newline at end of file diff --git a/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt b/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt index 4df03255..79cd02b9 100644 --- a/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt +++ b/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt @@ -6,7 +6,7 @@ import java.io.File import java.net.URI import java.net.URL -internal actual val Dispatchers.IO: CoroutineDispatcher get() = IO +internal actual val Dispatchers.IO: CoroutineDispatcher get() = kotlinx.coroutines.Dispatchers.IO internal actual typealias File = File diff --git a/kamel-core/src/nonJvmMain/kotlin/io/kamel/core/cache/LruCache.kt b/kamel-core/src/nonJvmMain/kotlin/io/kamel/core/cache/LruCache.kt new file mode 100644 index 00000000..7cd3a565 --- /dev/null +++ b/kamel-core/src/nonJvmMain/kotlin/io/kamel/core/cache/LruCache.kt @@ -0,0 +1,26 @@ +package io.kamel.core.cache + + +/** + * Cache implementation which evicts items using an LRU algorithm. + */ +internal actual class LruCache actual constructor(override val maxSize: Int) : Cache { + + private val cache: io.kamel.core.cache.common.LruCache = io.kamel.core.cache.common.LruCache(maxSize) + + override val size: Int + get() = cache.size() + + init { + require(maxSize >= 0) { "Cache max size must be positive number" } + } + + override fun get(key: K): V? = cache[key] + + override fun set(key: K, value: V) = cache.set(key, value) + + override fun remove(key: K): Boolean = cache.remove(key) != null + + override fun clear(): Unit = cache.clear() + +} \ No newline at end of file diff --git a/kamel-core/src/nonJvmMain/kotlin/io/kamel/core/cache/common/LruCache.kt b/kamel-core/src/nonJvmMain/kotlin/io/kamel/core/cache/common/LruCache.kt new file mode 100644 index 00000000..aa0f16fa --- /dev/null +++ b/kamel-core/src/nonJvmMain/kotlin/io/kamel/core/cache/common/LruCache.kt @@ -0,0 +1,161 @@ +package io.kamel.core.cache.common + +internal typealias Weigher = (Key, Value?) -> Int + +/** + * Multiplatform LRU cache implementation. + * https://github.com/apollographql/apollo-kotlin/blob/main/apollo-normalized-cache-api/src/commonMain/kotlin/com/apollographql/apollo3/cache/normalized/api/internal/LruCache.kt + * + * Implementation is based on usage of [LinkedHashMap] as a container for the cache and custom + * double linked queue to track LRU property. + * + * [maxSize] - maximum size of the cache, can be anything bytes, number of entries etc. By default is number o entries. + * [weigher] - to be called to calculate the estimated size (weight) of the cache entry defined by its [Key] and [Value]. + * By default it returns 1. + * + * Cache trim performed only on new entry insertion. + */ +internal class LruCache( + private val maxSize: Int, + private val weigher: Weigher = { _, _ -> 1 }, +) { + private val cache = LinkedHashMap>(0, 0.75f) + private var headNode: Node? = null + private var tailNode: Node? = null + private var size: Int = 0 + + operator fun get(key: Key): Value? { + val node = cache[key] + if (node != null) { + moveNodeToHead(node) + } + return node?.value + } + + operator fun set(key: Key, value: Value) { + val node = cache[key] + if (node == null) { + cache[key] = addNode(key, value) + } else { + node.value = value + moveNodeToHead(node) + } + + trim() + } + + fun remove(key: Key): Value? { + return removeUnsafe(key) + } + + fun keys() = cache.keys + + private fun removeUnsafe(key: Key): Value? { + val nodeToRemove = cache.remove(key) + val value = nodeToRemove?.value + if (nodeToRemove != null) { + unlinkNode(nodeToRemove) + } + return value + } + + fun remove(keys: Collection) { + keys.forEach { key -> removeUnsafe(key) } + } + + fun clear() { + cache.clear() + headNode = null + tailNode = null + size = 0 + } + + fun size(): Int { + return size + } + + fun dump(): Map { + return cache.mapValues { (_, value) -> + @Suppress("UNCHECKED_CAST") + value.value as Value + } + } + + private fun trim() { + var nodeToRemove = tailNode + while (nodeToRemove != null && size > maxSize) { + cache.remove(nodeToRemove.key) + unlinkNode(nodeToRemove) + nodeToRemove = tailNode + } + } + + private fun addNode(key: Key, value: Value?): Node { + val node = Node( + key = key, + value = value, + next = headNode, + prev = null, + ) + + headNode = node + + if (node.next == null) { + tailNode = headNode + } else { + node.next?.prev = headNode + } + + size += weigher(key, value) + + return node + } + + private fun moveNodeToHead(node: Node) { + if (node.prev == null) { + return + } + + node.prev?.next = node.next + + if (node.next == null) { + tailNode = node.prev + } else { + node.next?.prev = node.prev + } + + node.next = headNode + node.prev = null + + headNode?.prev = node + headNode = node + } + + private fun unlinkNode(node: Node) { + if (node.prev == null) { + this.headNode = node.next + } else { + node.prev?.next = node.next + } + + if (node.next == null) { + this.tailNode = node.prev + } else { + node.next?.prev = node.prev + } + + size -= weigher(node.key!!, node.value) + + node.key = null + node.value = null + node.next = null + node.prev = null + } + + private class Node( + var key: Key?, + var value: Value?, + var next: Node?, + var prev: Node?, + ) +} \ No newline at end of file diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 7a616cfb..ae29d2fe 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -56,6 +56,10 @@ kotlin { } jvm("desktop") + for (target in Targets.nativeTargets) { + targets.add(presets.getByName(target).createTarget(target)) + } + sourceSets { val commonMain by getting { @@ -67,31 +71,66 @@ kotlin { val commonTest by getting { dependencies { implementation(project(":kamel-tests")) - implementation(kotlin("test-common")) - implementation(kotlin("test-annotations-common")) + implementation(kotlin("test")) implementation(Dependencies.Testing.Ktor) - implementation(Dependencies.Testing.Compose) + implementation(Dependencies.Testing.Coroutines) } } - val desktopMain by getting + val jvmMain by creating { + dependsOn(commonMain) + } + + val jvmTest by creating { + dependsOn(commonTest) + dependencies{ + implementation(compose.material) + implementation(Dependencies.Testing.Compose) + } + } + + val desktopMain by getting { + dependsOn(jvmMain) + } val desktopTest by getting { + dependsOn(jvmTest) dependencies { implementation(Dependencies.Ktor.CIO) implementation(compose.desktop.currentOs) - implementation(kotlin("test-junit")) } } - val androidMain by getting + val androidMain by getting { + dependsOn(jvmMain) + } val androidTest by getting { - dependencies { - implementation(kotlin("test")) - implementation(kotlin("test-junit")) - implementation("androidx.test:core:1.4.0") - implementation("androidx.test.ext:junit:1.1.3") + dependsOn(jvmTest) + } + + val nonJvmMain by creating { + dependsOn(commonMain) + } + + val nonJvmTest by creating { + dependsOn(commonTest) + } + + val darwinMain by creating { + dependsOn(nonJvmMain) + } + + val darwinTest by creating { + dependsOn(nonJvmTest) + } + + Targets.darwinTargets.forEach { target -> + getByName("${target}Main") { + dependsOn(darwinMain) + } + getByName("${target}Test") { + dependsOn(darwinTest) } } @@ -101,13 +140,5 @@ kotlin { } } - targets.all { - compilations.all { - kotlinOptions { - freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn") - } - } - } - } } diff --git a/kamel-image/src/desktopTest/kotlin/io/kamel/image/fetcher/ResourcesFetcherTest.kt b/kamel-image/src/desktopTest/kotlin/io/kamel/image/fetcher/ResourcesFetcherTest.kt index 98e8acc1..637a57b7 100644 --- a/kamel-image/src/desktopTest/kotlin/io/kamel/image/fetcher/ResourcesFetcherTest.kt +++ b/kamel-image/src/desktopTest/kotlin/io/kamel/image/fetcher/ResourcesFetcherTest.kt @@ -22,15 +22,15 @@ class ResourcesFetcherTest { private val resourceConfig = ResourceConfigBuilder().build() @Test - fun testUrlIsSupported(): Unit = runTest { - val imageUrl = Url("Compose.png") + fun testUrlIsSupported() = runTest { + val imageUrl = Url("files/Compose.png") val isSupported = with(fetcher) { imageUrl.isSupported } assertTrue { isSupported } } @Test - fun testUrlIsNotSupported(): Unit = runTest { + fun testUrlIsNotSupported() = runTest { val imageUrl = Url("invalidImage.jpg") val isSupported = with(fetcher) { imageUrl.isSupported } @@ -38,8 +38,8 @@ class ResourcesFetcherTest { } @Test - fun loadImageBitmapResource(): Unit = runTest { - val imageUrl = Url("Compose.png") + fun loadImageBitmapResource() = runTest { + val imageUrl = Url("files/Compose.png") val resource = fetcher.fetch(imageUrl, resourceConfig) .first { !it.isLoading } .map { it.toByteArray() } @@ -49,7 +49,7 @@ class ResourcesFetcherTest { } @Test - fun loadInvalidImageResource(): Unit = runTest { + fun loadInvalidImageResource() = runTest { val imageUrl = Url("invalidImage.jpg") assertFailsWith { diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/config/KamelConfig.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/config/KamelConfig.kt new file mode 100644 index 00000000..edc02f67 --- /dev/null +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/config/KamelConfig.kt @@ -0,0 +1,15 @@ +package io.kamel.image.config + +import io.kamel.core.config.KamelConfigBuilder +import io.kamel.image.decoder.ImageVectorDecoder +import io.kamel.image.decoder.SvgDecoder +import io.kamel.image.fetcher.ResourcesFetcher + +/** + * Adds application resources fetcher to the [KamelConfigBuilder]. + */ +public fun KamelConfigBuilder.resourcesFetcher(): Unit = fetcher(ResourcesFetcher) + +public fun KamelConfigBuilder.imageVectorDecoder(): Unit = decoder(ImageVectorDecoder) + +public fun KamelConfigBuilder.svgDecoder(): Unit = decoder(SvgDecoder) \ No newline at end of file diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt new file mode 100644 index 00000000..e7c03a48 --- /dev/null +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt @@ -0,0 +1,19 @@ +package io.kamel.image.decoder + +import androidx.compose.ui.graphics.ImageBitmap +import io.kamel.core.config.ResourceConfig +import io.kamel.core.decoder.Decoder +import io.ktor.utils.io.* +import org.jetbrains.skia.Image + +/** + * Decodes and transfers [ByteReadChannel] to [ImageBitmap] using Skia [Image]. + */ +internal actual object ImageBitmapDecoder : Decoder { + + override suspend fun decode( + channel: ByteReadChannel, + resourceConfig: ResourceConfig + ): ImageBitmap = TODO() //Image.makeFromEncoded(channel.toByteArray()).toComposeImageBitmap() + +} \ No newline at end of file diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt new file mode 100644 index 00000000..ccf67738 --- /dev/null +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt @@ -0,0 +1,17 @@ +package io.kamel.image.decoder + +import androidx.compose.ui.graphics.vector.ImageVector +//import androidx.compose.ui.res.loadXmlImageVector +import io.kamel.core.config.ResourceConfig +import io.kamel.core.decoder.Decoder +import io.ktor.utils.io.* +//import io.ktor.utils.io.jvm.javaio.* +//import org.xml.sax.InputSource + +internal object ImageVectorDecoder : Decoder { + override suspend fun decode(channel: ByteReadChannel, resourceConfig: ResourceConfig): ImageVector { + TODO() +// val inputSource = InputSource(channel.toInputStream()) +// return loadXmlImageVector(inputSource, resourceConfig.density) + } +} \ No newline at end of file diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt new file mode 100644 index 00000000..36ab3339 --- /dev/null +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt @@ -0,0 +1,17 @@ +package io.kamel.image.decoder + +import androidx.compose.ui.graphics.painter.Painter +//import androidx.compose.ui.res.loadSvgPainter +import io.kamel.core.config.ResourceConfig +import io.kamel.core.decoder.Decoder +import io.ktor.utils.io.* +//import io.ktor.utils.io.jvm.javaio.* + +internal object SvgDecoder : Decoder { + override suspend fun decode(channel: ByteReadChannel, resourceConfig: ResourceConfig): Painter { + return TODO()/*loadSvgPainter( + channel.toInputStream(), + resourceConfig.density + )*/ + } +} \ No newline at end of file diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt new file mode 100644 index 00000000..897e5a34 --- /dev/null +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt @@ -0,0 +1,32 @@ +package io.kamel.image.fetcher + +import io.kamel.core.DataSource +import io.kamel.core.Resource +import io.kamel.core.config.ResourceConfig +import io.kamel.core.fetcher.Fetcher +import io.kamel.image.utils.path +import io.ktor.http.* +import io.ktor.utils.io.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow + +internal object ResourcesFetcher : Fetcher { + + override val source: DataSource = DataSource.Disk + + override val Url.isSupported: Boolean + get() = TODO()//Thread.currentThread().contextClassLoader?.getResource(path) != null + + override fun fetch( + data: Url, + resourceConfig: ResourceConfig + ): Flow> = flow { + TODO() +// val bytes = Thread.currentThread().contextClassLoader +// ?.getResource(data.path) +// ?.readBytes() +// ?.let { ByteReadChannel(it) } ?: error("Unable to find resource $data") +// emit(Resource.Success(bytes, source)) + } + +} \ No newline at end of file diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index 37b43c98..6f63862c 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -17,11 +17,6 @@ android { multiDexEnabled = true } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - packagingOptions { resources { excludes += setOf("META-INF/AL2.0", "META-INF/LGPL2.1") @@ -42,13 +37,13 @@ android { create("testApi") create("testDebugApi") create("testReleaseApi") - named("implementation") { - exclude(group = "androidx.compose.animation") - exclude(group = "androidx.compose.foundation") - exclude(group = "androidx.compose.material") - exclude(group = "androidx.compose.runtime") - exclude(group = "androidx.compose.ui") - } +// named("implementation") { +// exclude(group = "androidx.compose.animation") +// exclude(group = "androidx.compose.foundation") +// exclude(group = "androidx.compose.material") +// exclude(group = "androidx.compose.runtime") +// exclude(group = "androidx.compose.ui") +// } } } @@ -56,21 +51,22 @@ kotlin { explicitApi = ExplicitApiMode.Warning - android() - jvm("desktop") { - compilations.all { - kotlinOptions { - jvmTarget = "11" - } - } + jvmToolchain { + languageVersion.set(JavaLanguageVersion.of("11")) } + android() + jvm("desktop") + + sourceSets { val commonMain by getting { dependencies { implementation(project(":kamel-image")) implementation(project(":kamel-tests")) + implementation(compose.ui) + implementation(compose.foundation) implementation(compose.material) implementation(compose.animation) } @@ -78,8 +74,6 @@ kotlin { val androidMain by getting { dependencies { - implementation(Dependencies.Android.Appcompat) - implementation(Dependencies.Android.Core) implementation(Dependencies.Android.ActivityCompose) implementation(Dependencies.Android.Material) implementation(Dependencies.Ktor.Android) @@ -99,15 +93,12 @@ kotlin { } } - targets.all { - compilations.all { - kotlinOptions { - freeCompilerArgs = - listOf("-Xopt-in=kotlin.RequiresOptIn") - } - } - } + } +} +tasks.withType { + kotlinOptions { + jvmTarget = "11" } } diff --git a/kamel-samples/src/androidMain/kotlin/io/kamel/samples/ResourcesSample.kt b/kamel-samples/src/androidMain/kotlin/io/kamel/samples/ResourcesSample.kt index e694ccc0..26d05718 100644 --- a/kamel-samples/src/androidMain/kotlin/io/kamel/samples/ResourcesSample.kt +++ b/kamel-samples/src/androidMain/kotlin/io/kamel/samples/ResourcesSample.kt @@ -14,7 +14,6 @@ import io.kamel.image.config.Default import io.kamel.image.config.LocalKamelConfig import io.kamel.image.config.resourcesFetcher import io.kamel.image.config.resourcesIdMapper -import io.kamel.image.lazyImageResource import io.kamel.image.lazyPainterResource class ResourcesSample : AppCompatActivity() { diff --git a/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt index 8f524d72..586dcd2c 100644 --- a/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt +++ b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt @@ -2,9 +2,8 @@ package io.kamel.samples import androidx.compose.foundation.background import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.runtime.* @@ -38,7 +37,9 @@ public fun Gallery() { } Box(Modifier.fillMaxSize()) { - LazyVerticalGrid(columns = GridCells.Fixed(cellsCount), modifier = Modifier.fillMaxSize()) { + //https://github.com/JetBrains/compose-jb/issues/2061 +// LazyVerticalGrid(columns = GridCells.Fixed(cellsCount), modifier = Modifier.fillMaxSize()) { + LazyColumn(modifier = Modifier.fillMaxSize()) { items(items) { imageUrl -> val painterResource: Resource = lazyPainterResource( imageUrl, diff --git a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/ResourcesSample.kt b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/ResourcesSample.kt index 43c2b782..5b020d63 100644 --- a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/ResourcesSample.kt +++ b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/ResourcesSample.kt @@ -19,7 +19,7 @@ public fun main(): Unit = singleWindowApplication { } CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { - val painterResource = lazyPainterResource("Compose.png") + val painterResource = lazyPainterResource("MR/files/Compose.png") KamelImage( painterResource, diff --git a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/SvgSample.kt b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/SvgSample.kt index e527bdf5..0b5db5f8 100644 --- a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/SvgSample.kt +++ b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/SvgSample.kt @@ -21,7 +21,7 @@ public fun main(): Unit = singleWindowApplication { } CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { - val painterResource = lazyPainterResource("Kotlin.svg") + val painterResource = lazyPainterResource("MR/files/Kotlin.svg") KamelImage( painterResource, diff --git a/kamel-tests/build.gradle.kts b/kamel-tests/build.gradle.kts index 2e4ec16d..025c43f1 100644 --- a/kamel-tests/build.gradle.kts +++ b/kamel-tests/build.gradle.kts @@ -1,23 +1,50 @@ plugins { multiplatform + mokoResources } kotlin { jvm() + for (target in Targets.nativeTargets) { + targets.add(presets.getByName(target).createTarget(target)) + } sourceSets { val commonMain by getting { dependencies { implementation(Dependencies.Testing.Ktor) - implementation(Dependencies.Testing.Compose) implementation(Dependencies.Testing.Coroutines) + implementation(Dependencies.Testing.MokoResources) } } val commonTest by getting { dependencies { - implementation(kotlin("test-common")) - implementation(kotlin("test-annotations-common")) + implementation(kotlin("test")) + } + } + + val darwinMain by creating { + dependsOn(commonMain) + } + + val darwinTest by creating { + dependsOn(commonTest) + } + + Targets.darwinTargets.forEach { target -> + getByName("${target}Main") { + dependsOn(darwinMain) + } + getByName("${target}Test") { + dependsOn(darwinTest) } } } -} \ No newline at end of file +} + +multiplatformResources { + multiplatformResourcesPackage = "io.kamel.tests" +} + +tasks.findByName("jvmProcessResources")!!.dependsOn("generateMRcommonMain") +tasks.findByName("jvmProcessResources")!!.dependsOn("generateMRjvmMain") \ No newline at end of file diff --git a/kamel-tests/src/commonMain/resources/Compose.png b/kamel-tests/src/commonMain/resources/MR/files/Compose.png similarity index 100% rename from kamel-tests/src/commonMain/resources/Compose.png rename to kamel-tests/src/commonMain/resources/MR/files/Compose.png diff --git a/kamel-tests/src/commonMain/resources/Kotlin.svg b/kamel-tests/src/commonMain/resources/MR/files/Kotlin.svg similarity index 100% rename from kamel-tests/src/commonMain/resources/Kotlin.svg rename to kamel-tests/src/commonMain/resources/MR/files/Kotlin.svg diff --git a/kamel-tests/src/darwinMain/kotlin/io/kamel/tests/JvmTestUtils.kt b/kamel-tests/src/darwinMain/kotlin/io/kamel/tests/JvmTestUtils.kt new file mode 100644 index 00000000..5804f06f --- /dev/null +++ b/kamel-tests/src/darwinMain/kotlin/io/kamel/tests/JvmTestUtils.kt @@ -0,0 +1,17 @@ +package io.kamel.tests + +import io.ktor.utils.io.* +import io.ktor.utils.io.core.* + + +actual val resourceImage: ByteReadChannel + get() { + val bytes = MR.files.Compose.readText().encodeToByteArray() + return ByteReadChannel(bytes) + } + +actual val svgImage: ByteReadChannel + get() { + val bytes = MR.files.Kotlin.readText().encodeToByteArray() + return ByteReadChannel(bytes) + } diff --git a/kamel-tests/src/jvmMain/kotlin/io/kamel/tests/JvmTestUtils.kt b/kamel-tests/src/jvmMain/kotlin/io/kamel/tests/JvmTestUtils.kt index f510c80f..f69d9602 100644 --- a/kamel-tests/src/jvmMain/kotlin/io/kamel/tests/JvmTestUtils.kt +++ b/kamel-tests/src/jvmMain/kotlin/io/kamel/tests/JvmTestUtils.kt @@ -5,14 +5,12 @@ import io.ktor.utils.io.* actual val resourceImage: ByteReadChannel get() { - val url = Thread.currentThread().contextClassLoader.getResource("Compose.png")!! - val bytes = url.readBytes() + val bytes = MR.files.Compose.readText().encodeToByteArray() return ByteReadChannel(bytes) } actual val svgImage: ByteReadChannel get() { - val url = Thread.currentThread().contextClassLoader.getResource("Kotlin.svg")!! - val bytes = url.readBytes() + val bytes = MR.files.Kotlin.readText().encodeToByteArray() return ByteReadChannel(bytes) } From 23a21437c617c02b62a6743ee4abe47e31dbe18b Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Tue, 9 Aug 2022 21:09:49 -0400 Subject: [PATCH 04/74] Add a macOs native application sample --- buildSrc/src/main/kotlin/Dependencies.kt | 1 + gradle.properties | 1 + .../kotlin/io/kamel/core/utils/Platform.kt | 2 +- kamel-image/build.gradle.kts | 3 ++ kamel-samples/build.gradle.kts | 33 ++++++++++++++ .../kotlin/io/kamel/samples/FileSample.kt | 2 +- .../kotlin/io/kamel/samples/cellsCount.kt | 8 ++++ .../src/macosMain/kotlin/main.macos.kt | 44 +++++++++++++++++++ 8 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 kamel-samples/src/macosMain/kotlin/io/kamel/samples/cellsCount.kt create mode 100644 kamel-samples/src/macosMain/kotlin/main.macos.kt diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index d146fdee..e7c86bec 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -14,6 +14,7 @@ object Dependencies { const val Core = "io.ktor:ktor-client-core:${Versions.Ktor}" const val Logging = "io.ktor:ktor-client-logging:${Versions.Ktor}" const val Android = "io.ktor:ktor-client-android:${Versions.Ktor}" + const val Darwin = "io.ktor:ktor-client-darwin:${Versions.Ktor}" const val CIO = "io.ktor:ktor-client-cio:${Versions.Ktor}" } diff --git a/gradle.properties b/gradle.properties index 00afec92..a0e207d8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,6 +3,7 @@ kotlin.code.style=official kotlin.native.cacheKind=none kotlin.native.useEmbeddableCompilerJar=true kotlin.native.binary.memoryModel=experimental +kotlin.mpp.enableCInteropCommonization=true compose.desktop.verbose=true android.useAndroidX=true kotlin.mpp.stability.nowarn=true \ No newline at end of file diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt index 9de1e146..e915ed90 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt @@ -6,7 +6,7 @@ import platform.Foundation.NSFileHandle import platform.Foundation.NSURL -internal actual val Dispatchers.IO: CoroutineDispatcher get() = kotlinx.coroutines.Dispatchers.IO +internal actual val Dispatchers.IO: CoroutineDispatcher get() = kotlinx.coroutines.Dispatchers.Default internal actual typealias File = NSFileHandle diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index ae29d2fe..88d3a8eb 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -119,6 +119,9 @@ kotlin { val darwinMain by creating { dependsOn(nonJvmMain) + dependencies { + implementation(Dependencies.Ktor.Darwin) + } } val darwinTest by creating { diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index 6f63862c..d1989113 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -58,6 +58,19 @@ kotlin { android() jvm("desktop") + for (target in Targets.macosTargets) { + targets.add( + (presets.getByName(target) + .createTarget(target) as org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget).apply { + binaries.executable { + freeCompilerArgs += listOf( + "-linker-option", "-framework", "-linker-option", "Metal" + ) + } + } + ) + } + sourceSets { @@ -87,6 +100,16 @@ kotlin { } } + val macosMain by creating { + dependsOn(commonMain) + } + + Targets.macosTargets.forEach { target -> + getByName("${target}Main") { + dependsOn(macosMain) + } + } + all { languageSettings.apply { optIn("kotlin.Experimental") @@ -108,4 +131,14 @@ compose { mainClass = "io.kamel.samples.DesktopSampleKt" } } +} + + +compose.desktop.nativeApplication { + targets(kotlin.targets.getByName("macosArm64")) + distributions { + targetFormats(org.jetbrains.compose.desktop.application.dsl.TargetFormat.Dmg) + packageName = "Native-Sample" + packageVersion = "1.0.0" + } } \ No newline at end of file diff --git a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt index 50f7f259..7f73e7b6 100644 --- a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt +++ b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt @@ -23,7 +23,7 @@ public fun main(): Unit = singleWindowApplication { CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { val painterResource = - lazyPainterResource(File("kamel-tests/src/commonMain/resources/Compose.png")) + lazyPainterResource(File("kamel-tests/src/commonMain/resources/MR/files/Compose.png")) KamelImage( painterResource, diff --git a/kamel-samples/src/macosMain/kotlin/io/kamel/samples/cellsCount.kt b/kamel-samples/src/macosMain/kotlin/io/kamel/samples/cellsCount.kt new file mode 100644 index 00000000..f405dd5a --- /dev/null +++ b/kamel-samples/src/macosMain/kotlin/io/kamel/samples/cellsCount.kt @@ -0,0 +1,8 @@ +package io.kamel.samples + +import androidx.compose.ui.window.Window +import platform.AppKit.NSApp +import platform.AppKit.NSApplication + + +public actual val cellsCount: Int = 4 diff --git a/kamel-samples/src/macosMain/kotlin/main.macos.kt b/kamel-samples/src/macosMain/kotlin/main.macos.kt new file mode 100644 index 00000000..d89921fc --- /dev/null +++ b/kamel-samples/src/macosMain/kotlin/main.macos.kt @@ -0,0 +1,44 @@ +import androidx.compose.foundation.layout.Column +import androidx.compose.material.Text +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.window.Window +import io.kamel.core.config.KamelConfig +import io.kamel.core.config.takeFrom +import io.kamel.image.config.Default +import io.kamel.image.config.LocalKamelConfig +import io.kamel.image.config.imageVectorDecoder +import io.kamel.image.config.resourcesFetcher +import platform.AppKit.NSApp +import platform.AppKit.NSApplication + +fun main() { + NSApplication.sharedApplication() + Window("FileSample") { + FileSample() + } + NSApp?.run() +} + +@androidx.compose.runtime.Composable +fun FileSample() { + val kamelConfig = KamelConfig { + takeFrom(KamelConfig.Default) + resourcesFetcher() + imageVectorDecoder() + } + + CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { + Column { + Text("TEST") +// val painterResource = +// lazyPainterResource(NSFileHandle.fileHandleForReadingAtPath("kamel-tests/src/commonMain/resources/MR/files/Compose.png")!!) +// +// KamelImage( +// painterResource, +// contentDescription = "Compose", +// modifier = Modifier.fillMaxSize(), +// onFailure = { throw it } +// ) + } + } +} From 41b9bda5f8186fccfce88e8bbdd405360444edb8 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 10 Aug 2022 00:24:48 -0400 Subject: [PATCH 05/74] fix coroutines dependencies use coroutines core in commonMain --- buildSrc/src/main/kotlin/Dependencies.kt | 6 +++++- kamel-core/build.gradle.kts | 2 +- kamel-image/build.gradle.kts | 2 +- kamel-tests/build.gradle.kts | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index e7c86bec..4674df52 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -18,9 +18,13 @@ object Dependencies { const val CIO = "io.ktor:ktor-client-cio:${Versions.Ktor}" } + object Coroutines { + const val Core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.Coroutines}" + const val Test = "org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.Coroutines}" + } + object Testing { const val Ktor = "io.ktor:ktor-client-mock:${Versions.Ktor}" - const val Coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.Coroutines}" const val Compose = "org.jetbrains.compose.ui:ui-test-junit4:${Versions.Compose}" const val MokoResources = "dev.icerock.moko:resources:${Versions.MokoResources}" } diff --git a/kamel-core/build.gradle.kts b/kamel-core/build.gradle.kts index 9e7e13ac..34993930 100644 --- a/kamel-core/build.gradle.kts +++ b/kamel-core/build.gradle.kts @@ -62,7 +62,7 @@ kotlin { implementation(project(":kamel-tests")) implementation(kotlin("test")) implementation(Dependencies.Testing.Ktor) - implementation(Dependencies.Testing.Coroutines) + implementation(Dependencies.Coroutines.Test) } } diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 88d3a8eb..491e1ff4 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -73,7 +73,7 @@ kotlin { implementation(project(":kamel-tests")) implementation(kotlin("test")) implementation(Dependencies.Testing.Ktor) - implementation(Dependencies.Testing.Coroutines) + implementation(Dependencies.Coroutines.Test) } } diff --git a/kamel-tests/build.gradle.kts b/kamel-tests/build.gradle.kts index 025c43f1..92217124 100644 --- a/kamel-tests/build.gradle.kts +++ b/kamel-tests/build.gradle.kts @@ -13,7 +13,7 @@ kotlin { val commonMain by getting { dependencies { implementation(Dependencies.Testing.Ktor) - implementation(Dependencies.Testing.Coroutines) + implementation(Dependencies.Coroutines.Core) implementation(Dependencies.Testing.MokoResources) } } From d5dce9c790b7eb038394231f9647c3e7a10fef88 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 10 Aug 2022 00:28:51 -0400 Subject: [PATCH 06/74] remove essentially what is essentially a duplicate function --- .../io/kamel/image/LazyPainterResource.kt | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt b/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt index b86326c4..d3d82121 100644 --- a/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt +++ b/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt @@ -82,28 +82,3 @@ public inline fun lazyPainterResource( } } } - -/** - * Loads a [Painter] resource asynchronously. - * @param data Can be anything such as [String], [Url] or a [File]. - * @param key That is used in [remember] during composition, usually it's just [data]. - * @param filterQuality That is used by [BitmapPainter]. - * @param block Configuration for [ResourceConfig]. - * @return [Resource] Which contains a [Painter] that can be used to display an image using [KamelImage] or [KamelImageBox]. - * @see LocalKamelConfig - */ -@OptIn(ExperimentalKamelApi::class) -@Composable -public inline fun lazyPainterResource( - data: Any, - key: Any? = data, - filterQuality: FilterQuality = DrawScope.DefaultFilterQuality, - block: ResourceConfigBuilder.() -> Unit = {}, -): Resource = lazyPainterResource( - data, - key, - filterQuality, - onLoadingPainter = { null }, - onFailurePainter = { null }, - block -) \ No newline at end of file From dbdf4d4636304c8353fd5b9c9af681359e831710 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 10 Aug 2022 00:33:52 -0400 Subject: [PATCH 07/74] workaround compose issue for darwin: lambda w/ null return throws error For some reason composeable lambda functions on native macos throw an error and cause the application to crash. work around the issue by making result of composable lambdas non-null with the use of kotlin result --- .../io/kamel/image/LazyPainterResource.kt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt b/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt index d3d82121..a8530c75 100644 --- a/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt +++ b/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt @@ -15,6 +15,8 @@ import io.kamel.core.config.ResourceConfigBuilder import io.kamel.image.config.LocalKamelConfig import io.ktor.http.* +public class PainterFailure : Error("Failed to return a Painter") + /** * Loads a [Painter] resource asynchronously. * @param data Can be anything such as [String], [Url] or a [File]. @@ -36,8 +38,8 @@ public inline fun lazyPainterResource( data: Any, key: Any? = data, filterQuality: FilterQuality = DrawScope.DefaultFilterQuality, - noinline onLoadingPainter: @Composable (Float) -> Painter? = { null }, - noinline onFailurePainter: @Composable (Throwable) -> Painter? = { null }, + noinline onLoadingPainter: @Composable (Float) -> Result = { Result.failure(PainterFailure()) }, + noinline onFailurePainter: @Composable (Throwable) -> Result = { Result.failure(PainterFailure()) }, block: ResourceConfigBuilder.() -> Unit = {}, ): Resource { @@ -61,14 +63,17 @@ public inline fun lazyPainterResource( val painterResourceWithFallbacks = when (painterResource) { is Resource.Loading -> { val resource = painterResource as Resource.Loading - val painter = onLoadingPainter(resource.progress) - if (painter != null) Resource.Success(painter) else painterResource + onLoadingPainter(resource.progress) + .mapCatching { painter -> Resource.Success(painter) } + .getOrDefault(painterResource) } + is Resource.Success -> painterResource is Resource.Failure -> { val resource = painterResource as Resource.Failure - val painter = onFailurePainter(resource.exception) - if (painter != null) Resource.Success(painter) else painterResource + onFailurePainter(resource.exception) + .mapCatching { painter -> Resource.Success(painter) } + .getOrDefault(painterResource) } } From faed3c0febf00ee9b775314785485eb517dc670c Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 10 Aug 2022 00:34:24 -0400 Subject: [PATCH 08/74] suppress gradle build warning --- gradle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle.properties b/gradle.properties index a0e207d8..79a45598 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,4 +6,5 @@ kotlin.native.binary.memoryModel=experimental kotlin.mpp.enableCInteropCommonization=true compose.desktop.verbose=true android.useAndroidX=true +android.disableAutomaticComponentCreation=true kotlin.mpp.stability.nowarn=true \ No newline at end of file From b9fe9a8a59c9640b5b3a7d0881eb2b7a53a5a77f Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 10 Aug 2022 17:12:51 -0400 Subject: [PATCH 09/74] Implement working solution for mapInput on native mapInput does not work on native. On native, you cannot catch the error when calling map with the wrong input type. Rework by passing the kclass to mapInput Store mappers in map of KClass to Mapper Also in the mapper interface add inputKClass and outputKClass. inputKClass is used to store a mapper in the new mappers (KClass to Mapper) map in KamelConfigBuilder --- buildSrc/src/main/kotlin/Dependencies.kt | 2 + .../kotlin/io/kamel/core/ImageLoading.kt | 23 ++++++----- .../io/kamel/core/config/KamelConfig.kt | 3 +- .../kamel/core/config/KamelConfigBuilder.kt | 11 ++++-- .../kotlin/io/kamel/core/mapper/Mapper.kt | 7 +++- .../kotlin/io/kamel/core/mapper/Mappers.kt | 11 +++++- .../kotlin/io/kamel/core/utils/ConfigUtils.kt | 18 ++------- .../core/config/KamelConfigBuilderTest.kt | 23 +++++++---- .../kamel/core/config/KamelConfigUtilsTest.kt | 6 +-- .../io/kamel/core/fetcher/FileFetcher.kt | 8 +--- .../kotlin/io/kamel/core/mapper/Mappers.kt | 20 +++++++++- .../kotlin/io/kamel/core/utils/Platform.kt | 38 ++++++++++++++++--- .../io/kamel/core/utils/MappersUtils.kt | 4 +- .../kotlin/io/kamel/core/mapper/JvmMappers.kt | 19 +++++++++- .../kotlin/io/kamel/core/utils/JvmPlatform.kt | 5 +-- kamel-image/build.gradle.kts | 3 ++ .../kamel/image/mapper/ResourcesIdMapper.kt | 7 ++++ .../io/kamel/image/LazyPainterResource.kt | 4 +- 18 files changed, 148 insertions(+), 64 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 4674df52..2404dad7 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -8,6 +8,7 @@ object Dependencies { const val ActivityCompose = "androidx.activity:activity-compose:${Versions.Android.ActivityCompose}" const val GradlePlugin = "com.android.tools.build:gradle:${Versions.AGP}" const val Material = "com.google.android.material:material:${Versions.Android.Material}" + const val Annotation = "androidx.annotation:annotation:${Versions.Android.Annotation}" } object Ktor { @@ -43,6 +44,7 @@ object Versions { object Android { const val ActivityCompose = "1.5.1" const val Material = "1.6.1" + const val Annotation = "1.4.0" } } \ No newline at end of file diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/ImageLoading.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/ImageLoading.kt index e7a877ee..3ac12bf6 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/ImageLoading.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/ImageLoading.kt @@ -13,6 +13,7 @@ import io.kamel.core.utils.findDecoderFor import io.kamel.core.utils.findFetcherFor import io.kamel.core.utils.mapInput import kotlinx.coroutines.flow.* +import kotlin.reflect.KClass /** * Loads an [ImageBitmap]. This includes mapping, fetching, decoding and caching the image resource. @@ -21,10 +22,11 @@ import kotlinx.coroutines.flow.* * @see Mapper * @see Cache */ -public fun KamelConfig.loadImageBitmapResource( - data: Any, - resourceConfig: ResourceConfig -): Flow> = loadResource(data, resourceConfig, imageBitmapCache) +public fun KamelConfig.loadImageBitmapResource( + data: I, + resourceConfig: ResourceConfig, + dataKClass: KClass<*> = data::class, +): Flow> = loadResource(data, dataKClass, resourceConfig, imageBitmapCache) /** * Loads an [ImageVector]. This includes mapping, fetching, decoding and caching the image resource. @@ -35,8 +37,9 @@ public fun KamelConfig.loadImageBitmapResource( */ public fun KamelConfig.loadImageVectorResource( data: Any, - resourceConfig: ResourceConfig -): Flow> = loadResource(data, resourceConfig, imageVectorCache) + resourceConfig: ResourceConfig, + dataKClass: KClass<*> = data::class +): Flow> = loadResource(data, dataKClass, resourceConfig, imageVectorCache) /** * Loads SVG [Painter]. This includes mapping, fetching, decoding and caching the image resource. @@ -47,15 +50,17 @@ public fun KamelConfig.loadImageVectorResource( */ public fun KamelConfig.loadSvgResource( data: Any, - resourceConfig: ResourceConfig -): Flow> = loadResource(data, resourceConfig, svgCache) + resourceConfig: ResourceConfig, + dataKClass: KClass<*> = data::class +): Flow> = loadResource(data, dataKClass, resourceConfig, svgCache) private inline fun KamelConfig.loadResource( data: Any, + dataKClass: KClass<*>, resourceConfig: ResourceConfig, cache: Cache, ): Flow> = flow { - val output = mapInput(data) + val output = mapInput(data, dataKClass) val cachedData = cache[output] if (cachedData != null) { val resource = Resource.Success(cachedData, DataSource.Memory) diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/config/KamelConfig.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/config/KamelConfig.kt index 803a229a..fed090ee 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/config/KamelConfig.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/config/KamelConfig.kt @@ -7,6 +7,7 @@ import io.kamel.core.cache.Cache import io.kamel.core.decoder.Decoder import io.kamel.core.fetcher.Fetcher import io.kamel.core.mapper.Mapper +import kotlin.reflect.KClass public const val DefaultCacheSize: Int = 100 @@ -20,7 +21,7 @@ public interface KamelConfig { public val decoders: List> - public val mappers: List> + public val mappers: Map, Mapper> /** * Number of entries to cache. Default is 100. diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/config/KamelConfigBuilder.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/config/KamelConfigBuilder.kt index 8ba00f96..fff29124 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/config/KamelConfigBuilder.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/config/KamelConfigBuilder.kt @@ -15,10 +15,13 @@ import io.kamel.core.mapper.Mapper import io.kamel.core.mapper.StringMapper import io.kamel.core.mapper.URIMapper import io.kamel.core.mapper.URLMapper +import io.kamel.core.utils.URI +import io.kamel.core.utils.URL import io.ktor.client.* import io.ktor.client.engine.* import io.ktor.client.request.* import io.ktor.http.* +import kotlin.reflect.KClass public class KamelConfigBuilder { @@ -26,7 +29,7 @@ public class KamelConfigBuilder { internal val decoders: MutableList> = mutableListOf() - internal val mappers: MutableList> = mutableListOf() + internal val mappers: MutableMap, Mapper> = mutableMapOf() public var imageBitmapCacheSize: Int = 0 @@ -43,7 +46,7 @@ public class KamelConfigBuilder { } public fun mapper(mapper: Mapper) { - mappers += mapper as Mapper + mappers[mapper.inputKClass] = mapper as Mapper } public fun build(): KamelConfig = object : KamelConfig { @@ -52,7 +55,7 @@ public class KamelConfigBuilder { override val decoders: List> = this@KamelConfigBuilder.decoders - override val mappers: List> = this@KamelConfigBuilder.mappers + override val mappers: Map, Mapper> = this@KamelConfigBuilder.mappers override val imageBitmapCache: Cache = LruCache(imageBitmapCacheSize) @@ -120,7 +123,7 @@ public fun KamelConfigBuilder.takeFrom(config: KamelConfig): KamelConfigBuilder svgCacheSize = config.svgCache.maxSize config.fetchers.forEach { fetcher(it) } config.decoders.forEach { decoder(it) } - config.mappers.forEach { mapper(it) } + config.mappers.values.forEach { mapper(it) } return this } \ No newline at end of file diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/mapper/Mapper.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/mapper/Mapper.kt index bdccb32f..c426eff4 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/mapper/Mapper.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/mapper/Mapper.kt @@ -1,12 +1,17 @@ package io.kamel.core.mapper +import kotlin.reflect.KClass + /** * Mapper used to map input [I] to output [O]. * @see StringMapper * @see URLMapper * @see URIMapper */ -public fun interface Mapper { +public interface Mapper { + + public val inputKClass: KClass + public val outputKClass: KClass /** * Maps input [I] to output [O]. diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/mapper/Mappers.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/mapper/Mappers.kt index 4da863c1..2f8d94b8 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/mapper/Mappers.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/mapper/Mappers.kt @@ -3,8 +3,17 @@ package io.kamel.core.mapper import io.kamel.core.utils.URI import io.kamel.core.utils.URL import io.ktor.http.* +import kotlin.reflect.KClass -internal val StringMapper: Mapper = Mapper { Url(it) } +internal val StringMapper: Mapper = object : Mapper { + override val inputKClass: KClass + get() = String::class + override val outputKClass: KClass + get() = Url::class + + override fun map(input: String): Url = Url(input) + +} internal expect val URLMapper: Mapper diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/ConfigUtils.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/ConfigUtils.kt index 22b5ee70..c358df49 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/ConfigUtils.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/ConfigUtils.kt @@ -3,22 +3,10 @@ package io.kamel.core.utils import io.kamel.core.config.KamelConfig import io.kamel.core.decoder.Decoder import io.kamel.core.fetcher.Fetcher +import kotlin.reflect.KClass -internal fun KamelConfig.mapInput(input: Any): Any { - - var output: Any? = null - - mappers.findLast { - - output = try { - it.map(input) - } catch (e: Throwable) { - null - } - - output != null - } - +internal fun KamelConfig.mapInput(input: Any, inputKClass: KClass<*>): Any { + val output = mappers[inputKClass]?.map(input) return output ?: input } diff --git a/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigBuilderTest.kt b/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigBuilderTest.kt index 095abfb1..a50e4650 100644 --- a/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigBuilderTest.kt +++ b/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigBuilderTest.kt @@ -7,6 +7,8 @@ import io.kamel.core.mapper.Mapper import io.kamel.core.mapper.StringMapper import io.kamel.core.mapper.URIMapper import io.kamel.core.mapper.URLMapper +import io.kamel.core.utils.URI +import io.kamel.core.utils.URL import io.kamel.tests.HttpMockEngine import kotlin.test.BeforeTest import kotlin.test.Test @@ -43,7 +45,8 @@ class KamelConfigBuilderTest { builder.stringMapper() assertTrue { builder.mappers.size == 1 } - assertTrue { builder.mappers.contains>(StringMapper) } + assertTrue { builder.mappers.keys.contains(String::class) } + assertTrue { builder.mappers.values.contains>(StringMapper) } } @Test @@ -51,7 +54,8 @@ class KamelConfigBuilderTest { builder.urlMapper() assertTrue { builder.mappers.size == 1 } - assertTrue { builder.mappers.contains>(URLMapper) } + assertTrue { builder.mappers.keys.contains(URL::class) } + assertTrue { builder.mappers.values.contains>(URLMapper) } } @Test @@ -59,7 +63,8 @@ class KamelConfigBuilderTest { builder.uriMapper() assertTrue { builder.mappers.size == 1 } - assertTrue { builder.mappers.contains>(URIMapper) } + assertTrue { builder.mappers.keys.contains(URI::class) } + assertTrue { builder.mappers.values.contains>(URIMapper) } } @Test @@ -83,8 +88,10 @@ class KamelConfigBuilderTest { builder.takeFrom(configBuilder) assertTrue { builder.fetchers.contains>(FileFetcher) } - assertTrue { builder.mappers.contains>(URIMapper) } - assertTrue { builder.mappers.contains>(StringMapper) } + assertTrue { builder.mappers.keys.contains(URI::class) } + assertTrue { builder.mappers.values.contains>(URIMapper) } + assertTrue { builder.mappers.keys.contains(String::class) } + assertTrue { builder.mappers.values.contains>(StringMapper) } assertEquals(100, builder.build().imageBitmapCache.maxSize) } @@ -99,8 +106,10 @@ class KamelConfigBuilderTest { builder.takeFrom(configBuilder.build()) assertTrue { builder.fetchers.contains>(FileFetcher) } - assertTrue { builder.mappers.contains>(URIMapper) } - assertTrue { builder.mappers.contains>(StringMapper) } + assertTrue { builder.mappers.keys.contains(URI::class) } + assertTrue { builder.mappers.values.contains>(URIMapper) } + assertTrue { builder.mappers.keys.contains(String::class) } + assertTrue { builder.mappers.values.contains>(StringMapper) } assertEquals(100, builder.build().imageBitmapCache.maxSize) } diff --git a/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigUtilsTest.kt b/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigUtilsTest.kt index c089ff50..50b15f5e 100644 --- a/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigUtilsTest.kt +++ b/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigUtilsTest.kt @@ -26,21 +26,21 @@ class KamelConfigUtilsTest { @Test fun testMapStringInput() { - val result = config.mapInput(TestStringUrl) + val result = config.mapInput(TestStringUrl, String::class) assertTrue(result is Url) } @Test fun testMapURLInput() { - val result = config.mapInput(createURL(TestStringUrl)) + val result = config.mapInput(createURL(TestStringUrl), URL::class) assertTrue(result is Url) } @Test fun testMapURIInput() { - val result = config.mapInput(createURI(TestStringUrl)) + val result = config.mapInput(createURI(TestStringUrl), URI::class) assertTrue(result is Url) } diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt index 1432b7df..1a56140d 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt @@ -22,17 +22,11 @@ internal actual object FileFetcher : Fetcher { override val File.isSupported: Boolean get() = true// exists() && isFile - private fun NSData.toByteArray(): ByteArray = ByteArray(this@toByteArray.length.toInt()).apply { - usePinned { - memcpy(it.addressOf(0), this@toByteArray.bytes, this@toByteArray.length) - } - } - override fun fetch( data: File, resourceConfig: ResourceConfig ): Flow> = flow { - val bytes = ByteReadChannel(data.availableData.toByteArray()) + val bytes = ByteReadChannel(data.availableData) emit(Resource.Success(bytes, source)) } diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/mapper/Mappers.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/mapper/Mappers.kt index f1e0c8ec..99820f48 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/mapper/Mappers.kt +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/mapper/Mappers.kt @@ -3,7 +3,23 @@ package io.kamel.core.mapper import io.kamel.core.utils.URI import io.kamel.core.utils.URL import io.ktor.http.* +import kotlin.reflect.KClass -internal actual val URLMapper: Mapper = Mapper { URIMapper.map(it.absoluteString()!!) } +internal actual val URLMapper: Mapper = object : Mapper { + override val inputKClass: KClass + get() = URL::class + override val outputKClass: KClass + get() = Url::class -internal actual val URIMapper: Mapper = Mapper { Url(it) } \ No newline at end of file + override fun map(input: URL): Url = StringMapper.map(input.absoluteString()!!) +} + + +internal actual val URIMapper: Mapper = object : Mapper { + override val inputKClass: KClass + get() = URI::class + override val outputKClass: KClass + get() = Url::class + + override fun map(input: URI): Url = StringMapper.map(input.uri) +} \ No newline at end of file diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt index e915ed90..81a1c602 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt @@ -1,16 +1,44 @@ package io.kamel.core.utils +import kotlinx.cinterop.addressOf +import kotlinx.cinterop.usePinned import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers +import platform.Foundation.NSData import platform.Foundation.NSFileHandle import platform.Foundation.NSURL +import platform.Foundation.fileHandleForReadingAtPath +import platform.posix.memcpy -internal actual val Dispatchers.IO: CoroutineDispatcher get() = kotlinx.coroutines.Dispatchers.Default +internal actual val Dispatchers.IO: CoroutineDispatcher get() = Default -internal actual typealias File = NSFileHandle +public actual class File(public val path: String) { -@Suppress("CONFLICTING_OVERLOADS") -internal actual typealias URL = NSURL + private val fileHandle: NSFileHandle? = NSFileHandle.fileHandleForReadingAtPath(path) + public val availableData: ByteArray get() = fileHandle?.availableData?.toByteArray() ?: byteArrayOf() + override fun toString(): String = path +// memScoped { +// fileHandle ?: return@memScoped "null" +// println("File.toString()") +// val buffer = CharArray(MAXPATHLEN) { 0.toChar() } +// val result = buffer.usePinned { pinned -> +// fcntl(fileHandle.fileDescriptor, F_GETPATH, pinned.addressOf(0)) +// } +// println(result) +// return@memScoped buffer.joinToString("") +// } -internal actual typealias URI = String \ No newline at end of file + private fun NSData.toByteArray(): ByteArray = ByteArray(this@toByteArray.length.toInt()).apply { + usePinned { + memcpy(it.addressOf(0), this@toByteArray.bytes, this@toByteArray.length) + } + } + +} + +public actual class URL(public val nsUrl: NSURL) { + public fun absoluteString(): String? = nsUrl.absoluteString +} + +public actual class URI(public val uri: String) \ No newline at end of file diff --git a/kamel-core/src/darwinTest/kotlin/io/kamel/core/utils/MappersUtils.kt b/kamel-core/src/darwinTest/kotlin/io/kamel/core/utils/MappersUtils.kt index 9d382c6d..584f9c59 100644 --- a/kamel-core/src/darwinTest/kotlin/io/kamel/core/utils/MappersUtils.kt +++ b/kamel-core/src/darwinTest/kotlin/io/kamel/core/utils/MappersUtils.kt @@ -3,6 +3,6 @@ package io.kamel.core.utils import platform.Foundation.NSURL -internal actual fun createURL(url: String): URL = NSURL.URLWithString(url)!! +internal actual fun createURL(url: String): URL = URL(NSURL.URLWithString(url)!!) -internal actual fun createURI(url: String): URI = url \ No newline at end of file +internal actual fun createURI(url: String): URI = URI(url) \ No newline at end of file diff --git a/kamel-core/src/jvmMain/kotlin/io/kamel/core/mapper/JvmMappers.kt b/kamel-core/src/jvmMain/kotlin/io/kamel/core/mapper/JvmMappers.kt index 78e8e3f9..5fd23a9c 100644 --- a/kamel-core/src/jvmMain/kotlin/io/kamel/core/mapper/JvmMappers.kt +++ b/kamel-core/src/jvmMain/kotlin/io/kamel/core/mapper/JvmMappers.kt @@ -3,7 +3,22 @@ package io.kamel.core.mapper import io.kamel.core.utils.URI import io.kamel.core.utils.URL import io.ktor.http.* +import kotlin.reflect.KClass -internal actual val URLMapper: Mapper = Mapper { URIMapper.map(it.toURI()) } +internal actual val URLMapper: Mapper = object : Mapper { + override val inputKClass: KClass + get() = URL::class + override val outputKClass: KClass + get() = Url::class -internal actual val URIMapper: Mapper = Mapper { Url(it) } \ No newline at end of file + override fun map(input: URL): Url = Url(input.toURI()) +} + +internal actual val URIMapper: Mapper = object : Mapper { + override val inputKClass: KClass + get() = URI::class + override val outputKClass: KClass + get() = Url::class + + override fun map(input: URI): Url = Url(input) +} \ No newline at end of file diff --git a/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt b/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt index 79cd02b9..583fec62 100644 --- a/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt +++ b/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt @@ -2,13 +2,12 @@ package io.kamel.core.utils import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers -import java.io.File import java.net.URI import java.net.URL -internal actual val Dispatchers.IO: CoroutineDispatcher get() = kotlinx.coroutines.Dispatchers.IO +internal actual val Dispatchers.IO: CoroutineDispatcher get() = IO -internal actual typealias File = File +internal actual typealias File = java.io.File internal actual typealias URL = URL diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 491e1ff4..b52d6880 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -103,6 +103,9 @@ kotlin { val androidMain by getting { dependsOn(jvmMain) + dependencies{ + implementation(Dependencies.Android.Annotation) + } } val androidTest by getting { diff --git a/kamel-image/src/androidMain/kotlin/io/kamel/image/mapper/ResourcesIdMapper.kt b/kamel-image/src/androidMain/kotlin/io/kamel/image/mapper/ResourcesIdMapper.kt index caf2650f..1973c1f6 100644 --- a/kamel-image/src/androidMain/kotlin/io/kamel/image/mapper/ResourcesIdMapper.kt +++ b/kamel-image/src/androidMain/kotlin/io/kamel/image/mapper/ResourcesIdMapper.kt @@ -5,10 +5,17 @@ import android.content.Context import androidx.annotation.DrawableRes import io.kamel.core.mapper.Mapper import io.ktor.http.* +import kotlin.reflect.KClass internal class ResourcesIdMapper(private val context: Context) : Mapper<@receiver:DrawableRes Int, Url> { + override val inputKClass: KClass + get() = Int::class + + override val outputKClass: KClass + get() = Url::class + override fun map(@DrawableRes input: Int): Url { val packageName = context.packageName val protocol = URLProtocol(name = ContentResolver.SCHEME_ANDROID_RESOURCE, defaultPort = -1) diff --git a/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt b/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt index a8530c75..5615225f 100644 --- a/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt +++ b/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt @@ -34,8 +34,8 @@ public class PainterFailure : Error("Failed to return a Painter") */ @ExperimentalKamelApi @Composable -public inline fun lazyPainterResource( - data: Any, +public inline fun lazyPainterResource( + data: I, key: Any? = data, filterQuality: FilterQuality = DrawScope.DefaultFilterQuality, noinline onLoadingPainter: @Composable (Float) -> Result = { Result.failure(PainterFailure()) }, From 43179b5c876c6d03260b663921d5605ae6fddb90 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 10 Aug 2022 17:42:24 -0400 Subject: [PATCH 10/74] Implement bitmap decoder for non-jvm fix bitmap decoder import for android --- buildSrc/src/main/kotlin/Dependencies.kt | 2 ++ kamel-image/build.gradle.kts | 2 ++ .../kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 2404dad7..1851a905 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -9,6 +9,7 @@ object Dependencies { const val GradlePlugin = "com.android.tools.build:gradle:${Versions.AGP}" const val Material = "com.google.android.material:material:${Versions.Android.Material}" const val Annotation = "androidx.annotation:annotation:${Versions.Android.Annotation}" + const val UIGraphics = "androidx.compose.ui:ui-graphics:${Versions.Android.UIGraphics}" } object Ktor { @@ -45,6 +46,7 @@ object Versions { const val ActivityCompose = "1.5.1" const val Material = "1.6.1" const val Annotation = "1.4.0" + const val UIGraphics = "1.2.1" } } \ No newline at end of file diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index b52d6880..669031d1 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -105,6 +105,8 @@ kotlin { dependsOn(jvmMain) dependencies{ implementation(Dependencies.Android.Annotation) + //todo: remove when resolved https://github.com/JetBrains/compose-jb/issues/2238 + implementation(Dependencies.Android.UIGraphics) } } diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt index e7c03a48..702decee 100644 --- a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt @@ -1,8 +1,10 @@ package io.kamel.image.decoder import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.toComposeImageBitmap import io.kamel.core.config.ResourceConfig import io.kamel.core.decoder.Decoder +import io.ktor.util.* import io.ktor.utils.io.* import org.jetbrains.skia.Image @@ -14,6 +16,6 @@ internal actual object ImageBitmapDecoder : Decoder { override suspend fun decode( channel: ByteReadChannel, resourceConfig: ResourceConfig - ): ImageBitmap = TODO() //Image.makeFromEncoded(channel.toByteArray()).toComposeImageBitmap() + ): ImageBitmap = Image.makeFromEncoded(channel.toByteArray()).toComposeImageBitmap() } \ No newline at end of file From 0869df54bc38ac108c7cdc432c023efd65852e45 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 10 Aug 2022 18:22:30 -0400 Subject: [PATCH 11/74] implement findFetcherFor and findDecoderFor for darwin just like in `Mapper`, in `Fetcher` store `inputDataKClass` for the input data class of each `Fetcher` and in `Decoder` store the class of the output of the decoder in `outputKClass` use these to pick a suitable fetcher in findFetcherFor and a suitable decoder in findDecoderFor --- .../kotlin/io/kamel/core/decoder/Decoder.kt | 8 +++++- .../kotlin/io/kamel/core/fetcher/Fetcher.kt | 6 ++++ .../io/kamel/core/fetcher/HttpFetcher.kt | 3 ++ .../kamel/core/config/KamelConfigUtilsTest.kt | 4 +++ .../io/kamel/core/fetcher/FileFetcher.kt | 5 +++- .../kotlin/io/kamel/core/utils/ConfigUtils.kt | 28 +++++++------------ .../io/kamel/core/fetcher/JvmFileFetcher.kt | 3 ++ .../decoder/AndroidImageBitmapDecoder.kt | 3 ++ .../kamel/image/fetcher/ResourcesFetcher.kt | 3 ++ .../decoder/DesktopImageBitmapDecoder.kt | 3 ++ .../decoder/DesktopImageVectorDecoder.kt | 5 ++++ .../kamel/image/decoder/DesktopSvgDecoder.kt | 5 ++++ .../kamel/image/fetcher/ResourcesFetcher.kt | 4 +++ .../kamel/image/decoder/ImageBitmapDecoder.kt | 3 ++ .../kamel/image/decoder/ImageVectorDecoder.kt | 5 ++++ .../io/kamel/image/decoder/SvgDecoder.kt | 5 ++++ .../kamel/image/fetcher/ResourcesFetcher.kt | 5 +++- 17 files changed, 77 insertions(+), 21 deletions(-) diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/decoder/Decoder.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/decoder/Decoder.kt index fece079a..e1f6490f 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/decoder/Decoder.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/decoder/Decoder.kt @@ -2,11 +2,17 @@ package io.kamel.core.decoder import io.kamel.core.config.ResourceConfig import io.ktor.utils.io.* +import kotlin.reflect.KClass /** * Decodes [ByteReadChannel] to [T]. */ -public interface Decoder { +public interface Decoder { + + /** + * The KClass of the output of this decoder + */ + public val outputKClass: KClass /** * Decodes [channel] to [T]. diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/fetcher/Fetcher.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/fetcher/Fetcher.kt index 80a71252..bebdb8c4 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/fetcher/Fetcher.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/fetcher/Fetcher.kt @@ -5,12 +5,18 @@ import io.kamel.core.Resource import io.kamel.core.config.ResourceConfig import io.ktor.utils.io.* import kotlinx.coroutines.flow.Flow +import kotlin.reflect.KClass /** * Fetches and transfers data into a [ByteReadChannel] asynchronously. */ public interface Fetcher { + /** + * The KClass type for which this fetcher supports as a data input + */ + public val inputDataKClass: KClass + /** * Source from where data has been loaded. */ diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/fetcher/HttpFetcher.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/fetcher/HttpFetcher.kt index 7b6076b9..1045b57f 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/fetcher/HttpFetcher.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/fetcher/HttpFetcher.kt @@ -11,12 +11,15 @@ import io.ktor.http.* import io.ktor.utils.io.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.channelFlow +import kotlin.reflect.KClass /** * Fetcher that fetches [ByteReadChannel] from network using [Url]. */ internal class HttpFetcher(private val client: HttpClient) : Fetcher { + override val inputDataKClass: KClass = Url::class + override val source: DataSource = DataSource.Network override val Url.isSupported: Boolean diff --git a/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigUtilsTest.kt b/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigUtilsTest.kt index 50b15f5e..8efa2bc0 100644 --- a/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigUtilsTest.kt +++ b/kamel-core/src/commonTest/kotlin/io/kamel/core/config/KamelConfigUtilsTest.kt @@ -9,6 +9,7 @@ import io.kamel.tests.HttpMockEngine import io.kamel.tests.TestStringUrl import io.ktor.http.* import io.ktor.utils.io.* +import kotlin.reflect.KClass import kotlin.test.Test import kotlin.test.assertFails import kotlin.test.assertTrue @@ -79,6 +80,9 @@ class KamelConfigUtilsTest { fun KamelConfigBuilder.fakeImageBitmapDecoder() = decoder(FakeImageBitmapDecoder) private object FakeImageBitmapDecoder : Decoder { + + override val outputKClass: KClass = ImageBitmap::class + override suspend fun decode(channel: ByteReadChannel, resourceConfig: ResourceConfig): ImageBitmap { return ImageBitmap(1, 1) } diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt index 1a56140d..23a5d8a6 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt @@ -11,16 +11,19 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import platform.Foundation.NSData import platform.posix.memcpy +import kotlin.reflect.KClass /** * Fetcher that fetchers [ByteReadChannel] from a file. */ internal actual object FileFetcher : Fetcher { + override val inputDataKClass: KClass = File::class + override val source: DataSource = DataSource.Disk override val File.isSupported: Boolean - get() = true// exists() && isFile + get() = true override fun fetch( data: File, diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/ConfigUtils.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/ConfigUtils.kt index 485f03d7..00ef61f3 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/ConfigUtils.kt +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/ConfigUtils.kt @@ -5,44 +5,36 @@ package io.kamel.core.utils import io.kamel.core.config.KamelConfig import io.kamel.core.decoder.Decoder import io.kamel.core.fetcher.Fetcher -//import kotlin.reflect.full.createType -//import kotlin.reflect.full.isSubtypeOf -//import kotlin.reflect.full.isSupertypeOf import kotlin.reflect.typeOf internal actual fun KamelConfig.findFetcherFor(data: T): Fetcher { - val type = null //data::class.createType() + val type = data::class - val fetcher = null /*fetchers.findLast { fetcher -> + val fetcher = fetchers.findLast { fetcher -> - val fetcherType = fetcher::class.supertypes - .firstOrNull() - ?.arguments - ?.firstOrNull() - ?.type ?: error("Unable to find type for $fetcher") + val fetcherType = fetcher.inputDataKClass - val isSameType = fetcherType.isSupertypeOf(type) || fetcherType.isSubtypeOf(type) + val isSameType = fetcherType == type isSameType && with(fetcher) { data.isSupported } - }*/ + } checkNotNull(fetcher) { "Unable to find a fetcher for $type" } return fetcher as Fetcher } -@OptIn(ExperimentalStdlibApi::class) internal actual inline fun KamelConfig.findDecoderFor(): Decoder { - val type = typeOf>() + val type = T::class - val decoder = null /*decoders.findLast { decoder -> + val decoder = decoders.findLast { decoder -> - val decoderType = decoder::class.createType() + val decoderType = decoder.outputKClass - decoderType.isSupertypeOf(type) || decoderType.isSubtypeOf(type) - }*/ + decoderType == type + } checkNotNull(decoder) { "Unable to find a decoder for $type" } diff --git a/kamel-core/src/jvmMain/kotlin/io/kamel/core/fetcher/JvmFileFetcher.kt b/kamel-core/src/jvmMain/kotlin/io/kamel/core/fetcher/JvmFileFetcher.kt index dd2d7fec..ca988386 100644 --- a/kamel-core/src/jvmMain/kotlin/io/kamel/core/fetcher/JvmFileFetcher.kt +++ b/kamel-core/src/jvmMain/kotlin/io/kamel/core/fetcher/JvmFileFetcher.kt @@ -8,12 +8,15 @@ import io.ktor.utils.io.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import java.io.File +import kotlin.reflect.KClass /** * Fetcher that fetchers [ByteReadChannel] from a file. */ internal actual object FileFetcher : Fetcher { + override val inputDataKClass: KClass = File::class + override val source: DataSource = DataSource.Disk override val File.isSupported: Boolean diff --git a/kamel-image/src/androidMain/kotlin/io/kamel/image/decoder/AndroidImageBitmapDecoder.kt b/kamel-image/src/androidMain/kotlin/io/kamel/image/decoder/AndroidImageBitmapDecoder.kt index f395209c..3edda718 100644 --- a/kamel-image/src/androidMain/kotlin/io/kamel/image/decoder/AndroidImageBitmapDecoder.kt +++ b/kamel-image/src/androidMain/kotlin/io/kamel/image/decoder/AndroidImageBitmapDecoder.kt @@ -8,11 +8,14 @@ import io.kamel.core.config.ResourceConfig import io.kamel.core.decoder.Decoder import io.ktor.util.* import io.ktor.utils.io.* +import kotlin.reflect.KClass private const val Offset = 0 internal actual object ImageBitmapDecoder : Decoder { + override val outputKClass: KClass = ImageBitmap::class + override suspend fun decode(channel: ByteReadChannel, resourceConfig: ResourceConfig): ImageBitmap { val bytes = channel.toByteArray() val bitmap = BitmapFactory.decodeByteArray(bytes, Offset, bytes.size) as Bitmap diff --git a/kamel-image/src/androidMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt b/kamel-image/src/androidMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt index 212a1835..849aa2d1 100644 --- a/kamel-image/src/androidMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt +++ b/kamel-image/src/androidMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt @@ -12,10 +12,13 @@ import io.ktor.utils.io.* import io.ktor.utils.io.jvm.javaio.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow +import kotlin.reflect.KClass internal class ResourcesFetcher(private val context: Context) : Fetcher { + override val inputDataKClass: KClass = Url::class + override val source: DataSource = DataSource.Disk override val Url.isSupported: Boolean diff --git a/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopImageBitmapDecoder.kt b/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopImageBitmapDecoder.kt index 702decee..5d2c6c6f 100644 --- a/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopImageBitmapDecoder.kt +++ b/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopImageBitmapDecoder.kt @@ -7,12 +7,15 @@ import io.kamel.core.decoder.Decoder import io.ktor.util.* import io.ktor.utils.io.* import org.jetbrains.skia.Image +import kotlin.reflect.KClass /** * Decodes and transfers [ByteReadChannel] to [ImageBitmap] using Skia [Image]. */ internal actual object ImageBitmapDecoder : Decoder { + override val outputKClass: KClass = ImageBitmap::class + override suspend fun decode( channel: ByteReadChannel, resourceConfig: ResourceConfig diff --git a/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopImageVectorDecoder.kt b/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopImageVectorDecoder.kt index eba171d2..0cc0cae2 100644 --- a/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopImageVectorDecoder.kt +++ b/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopImageVectorDecoder.kt @@ -1,5 +1,6 @@ package io.kamel.image.decoder +import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.loadXmlImageVector import io.kamel.core.config.ResourceConfig @@ -7,8 +8,12 @@ import io.kamel.core.decoder.Decoder import io.ktor.utils.io.* import io.ktor.utils.io.jvm.javaio.* import org.xml.sax.InputSource +import kotlin.reflect.KClass internal object ImageVectorDecoder : Decoder { + + override val outputKClass: KClass = ImageVector::class + override suspend fun decode(channel: ByteReadChannel, resourceConfig: ResourceConfig): ImageVector { val inputSource = InputSource(channel.toInputStream()) return loadXmlImageVector(inputSource, resourceConfig.density) diff --git a/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopSvgDecoder.kt b/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopSvgDecoder.kt index bbb7f263..16ce2fae 100644 --- a/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopSvgDecoder.kt +++ b/kamel-image/src/desktopMain/kotlin/io/kamel/image/decoder/DesktopSvgDecoder.kt @@ -1,13 +1,18 @@ package io.kamel.image.decoder import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.loadSvgPainter import io.kamel.core.config.ResourceConfig import io.kamel.core.decoder.Decoder import io.ktor.utils.io.* import io.ktor.utils.io.jvm.javaio.* +import kotlin.reflect.KClass internal object SvgDecoder : Decoder { + + override val outputKClass: KClass = Painter::class + override suspend fun decode(channel: ByteReadChannel, resourceConfig: ResourceConfig): Painter { return loadSvgPainter( channel.toInputStream(), diff --git a/kamel-image/src/desktopMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt b/kamel-image/src/desktopMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt index a76794eb..726b08e4 100644 --- a/kamel-image/src/desktopMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt +++ b/kamel-image/src/desktopMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt @@ -9,9 +9,13 @@ import io.ktor.http.* import io.ktor.utils.io.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow +import java.io.File +import kotlin.reflect.KClass internal object ResourcesFetcher : Fetcher { + override val inputDataKClass: KClass = Url::class + override val source: DataSource = DataSource.Disk override val Url.isSupported: Boolean diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt index 702decee..5d2c6c6f 100644 --- a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageBitmapDecoder.kt @@ -7,12 +7,15 @@ import io.kamel.core.decoder.Decoder import io.ktor.util.* import io.ktor.utils.io.* import org.jetbrains.skia.Image +import kotlin.reflect.KClass /** * Decodes and transfers [ByteReadChannel] to [ImageBitmap] using Skia [Image]. */ internal actual object ImageBitmapDecoder : Decoder { + override val outputKClass: KClass = ImageBitmap::class + override suspend fun decode( channel: ByteReadChannel, resourceConfig: ResourceConfig diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt index ccf67738..55e4cd1e 100644 --- a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt @@ -5,10 +5,15 @@ import androidx.compose.ui.graphics.vector.ImageVector import io.kamel.core.config.ResourceConfig import io.kamel.core.decoder.Decoder import io.ktor.utils.io.* +import kotlin.reflect.KClass + //import io.ktor.utils.io.jvm.javaio.* //import org.xml.sax.InputSource internal object ImageVectorDecoder : Decoder { + + override val outputKClass: KClass = ImageVector::class + override suspend fun decode(channel: ByteReadChannel, resourceConfig: ResourceConfig): ImageVector { TODO() // val inputSource = InputSource(channel.toInputStream()) diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt index 36ab3339..4b9d854d 100644 --- a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt @@ -5,9 +5,14 @@ import androidx.compose.ui.graphics.painter.Painter import io.kamel.core.config.ResourceConfig import io.kamel.core.decoder.Decoder import io.ktor.utils.io.* +import kotlin.reflect.KClass + //import io.ktor.utils.io.jvm.javaio.* internal object SvgDecoder : Decoder { + + override val outputKClass: KClass = Painter::class + override suspend fun decode(channel: ByteReadChannel, resourceConfig: ResourceConfig): Painter { return TODO()/*loadSvgPainter( channel.toInputStream(), diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt index 897e5a34..47450d2d 100644 --- a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt @@ -9,13 +9,16 @@ import io.ktor.http.* import io.ktor.utils.io.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow +import kotlin.reflect.KClass internal object ResourcesFetcher : Fetcher { + override val inputDataKClass: KClass = Url::class + override val source: DataSource = DataSource.Disk override val Url.isSupported: Boolean - get() = TODO()//Thread.currentThread().contextClassLoader?.getResource(path) != null + get() = false//Thread.currentThread().contextClassLoader?.getResource(path) != null override fun fetch( data: Url, From 54cd4918fa38a63d64364a77101c4289092c5580 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 10 Aug 2022 19:00:12 -0400 Subject: [PATCH 12/74] add back removed "duplicate" lazyPainterResource it hides the ExperimentalKamelApi opt in requirement --- .../io/kamel/image/LazyPainterResource.kt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt b/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt index 5615225f..3a32603c 100644 --- a/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt +++ b/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt @@ -87,3 +87,29 @@ public inline fun lazyPainterResource( } } } + + +/** + * Loads a [Painter] resource asynchronously. + * @param data Can be anything such as [String], [Url] or a [File]. + * @param key That is used in [remember] during composition, usually it's just [data]. + * @param filterQuality That is used by [BitmapPainter]. + * @param block Configuration for [ResourceConfig]. + * @return [Resource] Which contains a [Painter] that can be used to display an image using [KamelImage] or [KamelImageBox]. + * @see LocalKamelConfig + */ +@OptIn(ExperimentalKamelApi::class) +@Composable +public inline fun lazyPainterResource( + data: Any, + key: Any? = data, + filterQuality: FilterQuality = DrawScope.DefaultFilterQuality, + block: ResourceConfigBuilder.() -> Unit = {}, +): Resource = lazyPainterResource( + data, + key, + filterQuality, + onLoadingPainter = { Result.failure(PainterFailure()) }, + onFailurePainter = { Result.failure(PainterFailure()) }, + block +) \ No newline at end of file From 1e6774a9726583f2dc6e5f98ea38ce4b9eeed826 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 10 Aug 2022 19:02:47 -0400 Subject: [PATCH 13/74] fix adding moko resources to native app bundle in native desktop sample --- kamel-samples/build.gradle.kts | 73 +++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index d1989113..3c19bb50 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -1,4 +1,11 @@ +import org.jetbrains.compose.desktop.application.tasks.AbstractNativeMacApplicationPackageAppDirTask import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode +import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractExecutable +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBinary +import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink +import org.jetbrains.kotlin.library.impl.KotlinLibraryLayoutImpl +import org.jetbrains.kotlin.konan.file.File as KonanFile +import java.io.FileFilter plugins { multiplatform @@ -94,6 +101,7 @@ kotlin { } val desktopMain by getting { + dependsOn(commonMain) dependencies { implementation(compose.desktop.currentOs) implementation(Dependencies.Ktor.CIO) @@ -141,4 +149,67 @@ compose.desktop.nativeApplication { packageName = "Native-Sample" packageVersion = "1.0.0" } -} \ No newline at end of file +} + + +// todo: Remove when resolved: https://github.com/icerockdev/moko-resources/issues/372 +tasks.withType() + .matching { linkTask -> linkTask.binary is AbstractExecutable } + .configureEach { + val task: KotlinNativeLink = this + + doLast { + val binary: NativeBinary = task.binary + val outputDir: File = task.outputFile.get().parentFile + task.libraries + .filter { library -> library.extension == "klib" } + .filter(File::exists) + .forEach { inputFile -> + val klibKonan = KonanFile(inputFile.path) + val klib = KotlinLibraryLayoutImpl( + klib = klibKonan, + component = "default" + ) + val layout = klib.extractingToTemp + + // extracting bundles + layout + .resourcesDir + .absolutePath + .let(::File) + .listFiles(FileFilter { it.extension == "bundle" }) + // copying bundles to app + ?.forEach { bundleFile -> + logger.info("${bundleFile.absolutePath} copying to $outputDir") + bundleFile.copyRecursively( + target = File(outputDir, bundleFile.name), + overwrite = true + ) + } + } + } + } + +tasks.withType { + val task: AbstractNativeMacApplicationPackageAppDirTask = this + + doLast { + val execFile: File = task.executable.get().asFile + val execDir: File = execFile.parentFile + val destDir: File = task.destinationDir.asFile.get() + val bundleID: String = task.bundleID.get() + + val outputDir = File(destDir, "$bundleID.app/Contents/Resources") + outputDir.mkdirs() + + execDir.listFiles().orEmpty() + .filter { it.extension == "bundle" } + .forEach { bundleFile -> + logger.info("${bundleFile.absolutePath} copying to $outputDir") + bundleFile.copyRecursively( + target = File(outputDir, bundleFile.name), + overwrite = true + ) + } + } +} From bda67f50353fef03d678304a3861f3757c0a1751 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 10 Aug 2022 19:03:36 -0400 Subject: [PATCH 14/74] Switch between file and gallery samples on macos. load file using MR Load file resources with moko-resources --- .../kotlin/io/kamel/samples/FileSample.kt | 3 +- .../kotlin/io/kamel/samples/FileSample.kt | 41 ++++++++++++ .../src/macosMain/kotlin/main.macos.kt | 64 +++++++++---------- kamel-tests/build.gradle.kts | 1 + 4 files changed, 74 insertions(+), 35 deletions(-) create mode 100644 kamel-samples/src/macosMain/kotlin/io/kamel/samples/FileSample.kt diff --git a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt index 7f73e7b6..7d856938 100644 --- a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt +++ b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt @@ -13,6 +13,7 @@ import io.kamel.image.config.imageVectorDecoder import io.kamel.image.config.resourcesFetcher import io.kamel.image.lazyPainterResource import java.io.File +import io.kamel.tests.MR public fun main(): Unit = singleWindowApplication { val kamelConfig = KamelConfig { @@ -23,7 +24,7 @@ public fun main(): Unit = singleWindowApplication { CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { val painterResource = - lazyPainterResource(File("kamel-tests/src/commonMain/resources/MR/files/Compose.png")) + lazyPainterResource(File(MR.files.Compose.filePath)) KamelImage( painterResource, diff --git a/kamel-samples/src/macosMain/kotlin/io/kamel/samples/FileSample.kt b/kamel-samples/src/macosMain/kotlin/io/kamel/samples/FileSample.kt new file mode 100644 index 00000000..2f5e71e2 --- /dev/null +++ b/kamel-samples/src/macosMain/kotlin/io/kamel/samples/FileSample.kt @@ -0,0 +1,41 @@ +package io.kamel.samples + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.Text +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import io.kamel.core.ExperimentalKamelApi +import io.kamel.core.config.KamelConfig +import io.kamel.core.config.takeFrom +import io.kamel.core.utils.File +import io.kamel.image.KamelImage +import io.kamel.image.config.Default +import io.kamel.image.config.LocalKamelConfig +import io.kamel.image.config.imageVectorDecoder +import io.kamel.image.config.resourcesFetcher +import io.kamel.image.lazyPainterResource + +@OptIn(ExperimentalKamelApi::class) +@androidx.compose.runtime.Composable +internal fun FileSample() { + val kamelConfig = KamelConfig { + takeFrom(KamelConfig.Default) + resourcesFetcher() + imageVectorDecoder() + } + + CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { + Column { + val file = File(io.kamel.tests.MR.files.Compose.path) + val painterResource = lazyPainterResource(file) + + KamelImage( + painterResource, + contentDescription = "Compose", + modifier = Modifier.fillMaxSize(), + onFailure = { throw it } + ) + } + } +} diff --git a/kamel-samples/src/macosMain/kotlin/main.macos.kt b/kamel-samples/src/macosMain/kotlin/main.macos.kt index d89921fc..18163e2a 100644 --- a/kamel-samples/src/macosMain/kotlin/main.macos.kt +++ b/kamel-samples/src/macosMain/kotlin/main.macos.kt @@ -1,44 +1,40 @@ import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.material.Button import androidx.compose.material.Text -import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.window.Window -import io.kamel.core.config.KamelConfig -import io.kamel.core.config.takeFrom -import io.kamel.image.config.Default -import io.kamel.image.config.LocalKamelConfig -import io.kamel.image.config.imageVectorDecoder -import io.kamel.image.config.resourcesFetcher +import io.kamel.samples.FileSample +import io.kamel.samples.Gallery import platform.AppKit.NSApp import platform.AppKit.NSApplication -fun main() { +public fun main() { NSApplication.sharedApplication() - Window("FileSample") { - FileSample() - } - NSApp?.run() -} - -@androidx.compose.runtime.Composable -fun FileSample() { - val kamelConfig = KamelConfig { - takeFrom(KamelConfig.Default) - resourcesFetcher() - imageVectorDecoder() - } - - CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { + Window("Sample") { + var sampleIndex by remember { mutableStateOf(0) } Column { - Text("TEST") -// val painterResource = -// lazyPainterResource(NSFileHandle.fileHandleForReadingAtPath("kamel-tests/src/commonMain/resources/MR/files/Compose.png")!!) -// -// KamelImage( -// painterResource, -// contentDescription = "Compose", -// modifier = Modifier.fillMaxSize(), -// onFailure = { throw it } -// ) + Row { + Button({ + sampleIndex = 0 + }) { + Text("Gallery") + } + Button({ + sampleIndex = 1 + }) { + Text("FileSample") + } + } + when (sampleIndex) { + 0 -> Gallery() + 1 -> FileSample() + else -> Text("Invalid Sample Index") + } } } -} + NSApp?.run() +} \ No newline at end of file diff --git a/kamel-tests/build.gradle.kts b/kamel-tests/build.gradle.kts index 92217124..0fb54c45 100644 --- a/kamel-tests/build.gradle.kts +++ b/kamel-tests/build.gradle.kts @@ -12,6 +12,7 @@ kotlin { sourceSets { val commonMain by getting { dependencies { + implementation(project(":kamel-core")) implementation(Dependencies.Testing.Ktor) implementation(Dependencies.Coroutines.Core) implementation(Dependencies.Testing.MokoResources) From 9a83662328143342ecc903b57040b7f47db504c4 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 10 Aug 2022 19:19:53 -0400 Subject: [PATCH 15/74] expose moko-rosources to kamel-samples There was an import error on jvm Also add moko-resources test dependency and expose it as well --- buildSrc/src/main/kotlin/Dependencies.kt | 5 +++++ kamel-tests/build.gradle.kts | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 1851a905..ff830c59 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -31,6 +31,11 @@ object Dependencies { const val MokoResources = "dev.icerock.moko:resources:${Versions.MokoResources}" } + object MokoResources { + const val Core = "dev.icerock.moko:resources:${Versions.MokoResources}" + const val Test = "dev.icerock.moko:resources-test:${Versions.MokoResources}" + } + } object Versions { diff --git a/kamel-tests/build.gradle.kts b/kamel-tests/build.gradle.kts index 0fb54c45..7dab709e 100644 --- a/kamel-tests/build.gradle.kts +++ b/kamel-tests/build.gradle.kts @@ -15,12 +15,13 @@ kotlin { implementation(project(":kamel-core")) implementation(Dependencies.Testing.Ktor) implementation(Dependencies.Coroutines.Core) - implementation(Dependencies.Testing.MokoResources) + api(Dependencies.MokoResources.Core) } } val commonTest by getting { dependencies { implementation(kotlin("test")) + api(Dependencies.MokoResources.Test) } } From e3b58c0768c3993c13489a7f9cfceb640aa2e3a2 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Fri, 12 Aug 2022 00:48:08 -0400 Subject: [PATCH 16/74] use java 11 everywhere. gradle cleanup and add todo notes --- build.gradle.kts | 1 + buildSrc/src/main/kotlin/Dependencies.kt | 2 ++ kamel-core/build.gradle.kts | 1 + kamel-image/build.gradle.kts | 13 ++++++---- kamel-samples/build.gradle.kts | 30 ++++++++++-------------- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 480a5d1a..ad1ec56e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -128,6 +128,7 @@ allprojects { tasks.withType { kotlinOptions { freeCompilerArgs = listOf("-Xallow-result-return-type") + jvmTarget = "11" } } diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index ff830c59..0353a39b 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -6,6 +6,7 @@ object Dependencies { object Android { const val ActivityCompose = "androidx.activity:activity-compose:${Versions.Android.ActivityCompose}" + const val Appcompat = "androidx.appcompat:appcompat:${Versions.Android.Appcompat}" const val GradlePlugin = "com.android.tools.build:gradle:${Versions.AGP}" const val Material = "com.google.android.material:material:${Versions.Android.Material}" const val Annotation = "androidx.annotation:annotation:${Versions.Android.Annotation}" @@ -49,6 +50,7 @@ object Versions { object Android { const val ActivityCompose = "1.5.1" + const val Appcompat = "1.4.2" const val Material = "1.6.1" const val Annotation = "1.4.0" const val UIGraphics = "1.2.1" diff --git a/kamel-core/build.gradle.kts b/kamel-core/build.gradle.kts index 34993930..b8d71526 100644 --- a/kamel-core/build.gradle.kts +++ b/kamel-core/build.gradle.kts @@ -67,6 +67,7 @@ kotlin { } val jvmMain by getting { + dependsOn(commonMain) dependencies { implementation(Dependencies.KotlinReflect) } diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 669031d1..95547be4 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -19,8 +19,8 @@ android { } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } testOptions { @@ -83,12 +83,12 @@ kotlin { val jvmTest by creating { dependsOn(commonTest) - dependencies{ + dependencies { implementation(compose.material) implementation(Dependencies.Testing.Compose) } } - + val desktopMain by getting { dependsOn(jvmMain) } @@ -104,8 +104,11 @@ kotlin { val androidMain by getting { dependsOn(jvmMain) dependencies{ + //todo: remove below when resolved https://github.com/JetBrains/compose-jb/issues/2238 + // the app will build without these imports. But Intellij highlights the compose + // imports in red if we do not add them here. (this is with the android 7.2 + // gradle plugin, 7.1 works correctly but causes lint errors when building) implementation(Dependencies.Android.Annotation) - //todo: remove when resolved https://github.com/JetBrains/compose-jb/issues/2238 implementation(Dependencies.Android.UIGraphics) } } diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index 3c19bb50..33c96fa0 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -1,3 +1,4 @@ +import org.jetbrains.compose.compose import org.jetbrains.compose.desktop.application.tasks.AbstractNativeMacApplicationPackageAppDirTask import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractExecutable @@ -24,6 +25,11 @@ android { multiDexEnabled = true } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + packagingOptions { resources { excludes += setOf("META-INF/AL2.0", "META-INF/LGPL2.1") @@ -44,13 +50,6 @@ android { create("testApi") create("testDebugApi") create("testReleaseApi") -// named("implementation") { -// exclude(group = "androidx.compose.animation") -// exclude(group = "androidx.compose.foundation") -// exclude(group = "androidx.compose.material") -// exclude(group = "androidx.compose.runtime") -// exclude(group = "androidx.compose.ui") -// } } } @@ -85,18 +84,21 @@ kotlin { dependencies { implementation(project(":kamel-image")) implementation(project(":kamel-tests")) - implementation(compose.ui) - implementation(compose.foundation) - implementation(compose.material) - implementation(compose.animation) } } val androidMain by getting { + dependsOn(commonMain) dependencies { + implementation(Dependencies.Android.Appcompat) implementation(Dependencies.Android.ActivityCompose) implementation(Dependencies.Android.Material) implementation(Dependencies.Ktor.Android) + //todo: remove below when resolved https://github.com/JetBrains/compose-jb/issues/2238 + // the app will build without these imports. But Intellij highlights the compose + // imports in red if we do not add them here. (this is with the android 7.2 + // gradle plugin, 7.1 works correctly but causes lint errors when building) + implementation("androidx.compose.foundation:foundation:1.2.1") } } @@ -127,12 +129,6 @@ kotlin { } } -tasks.withType { - kotlinOptions { - jvmTarget = "11" - } -} - compose { desktop { application { From fd6bf4014c333b0056608557f2a0d7a36cbbad60 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Mon, 12 Sep 2022 21:28:17 -0400 Subject: [PATCH 17/74] update compose-jb --- buildSrc/src/main/kotlin/Dependencies.kt | 2 +- gradle.properties | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 0353a39b..4d209fa7 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -44,7 +44,7 @@ object Versions { const val Kotlin = "1.7.10" const val Ktor = "2.0.3" const val Coroutines = "1.6.4" - const val Compose = "1.2.0-alpha01-dev745" + const val Compose = "1.2.0-alpha01-dev778" const val AGP = "7.2.2" const val MokoResources = "0.20.1" diff --git a/gradle.properties b/gradle.properties index 79a45598..893c578b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,8 @@ kotlin.mpp.enableCInteropCommonization=true compose.desktop.verbose=true android.useAndroidX=true android.disableAutomaticComponentCreation=true -kotlin.mpp.stability.nowarn=true \ No newline at end of file +kotlin.mpp.stability.nowarn=true + +org.jetbrains.compose.experimental.jscanvas.enabled=true +org.jetbrains.compose.experimental.macos.enabled=true +org.jetbrains.compose.experimental.uikit.enabled=true \ No newline at end of file From a856877b9748ca1c110576af6c5c452d6939ea7f Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Mon, 12 Sep 2022 21:28:30 -0400 Subject: [PATCH 18/74] update gradle --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1d8896d0..e5a24066 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sun Jul 10 06:06:14 TRT 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME \ No newline at end of file From 3f1d7fc91a01e330e9aa472ea3e18881772d6f55 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Mon, 12 Sep 2022 22:41:10 -0400 Subject: [PATCH 19/74] AGP to 7.3.0-rc01 (Must use android studio, see notes), remove todos https://youtrack.jetbrains.com/issue/IDEA-280006/Improve-Android-plugin-merging-cadence https://github.com/JetBrains/compose-jb/issues/2238 --- buildSrc/src/main/kotlin/Dependencies.kt | 2 +- kamel-image/build.gradle.kts | 8 -------- .../kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt | 1 - kamel-samples/build.gradle.kts | 6 +----- 4 files changed, 2 insertions(+), 15 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 4d209fa7..da341762 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -45,7 +45,7 @@ object Versions { const val Ktor = "2.0.3" const val Coroutines = "1.6.4" const val Compose = "1.2.0-alpha01-dev778" - const val AGP = "7.2.2" + const val AGP = "7.3.0-rc01" const val MokoResources = "0.20.1" object Android { diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 95547be4..45d19907 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -103,14 +103,6 @@ kotlin { val androidMain by getting { dependsOn(jvmMain) - dependencies{ - //todo: remove below when resolved https://github.com/JetBrains/compose-jb/issues/2238 - // the app will build without these imports. But Intellij highlights the compose - // imports in red if we do not add them here. (this is with the android 7.2 - // gradle plugin, 7.1 works correctly but causes lint errors when building) - implementation(Dependencies.Android.Annotation) - implementation(Dependencies.Android.UIGraphics) - } } val androidTest by getting { diff --git a/kamel-image/src/desktopMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt b/kamel-image/src/desktopMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt index 726b08e4..4c0e2d76 100644 --- a/kamel-image/src/desktopMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt +++ b/kamel-image/src/desktopMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt @@ -9,7 +9,6 @@ import io.ktor.http.* import io.ktor.utils.io.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow -import java.io.File import kotlin.reflect.KClass internal object ResourcesFetcher : Fetcher { diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index 33c96fa0..3636ad97 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -84,6 +84,7 @@ kotlin { dependencies { implementation(project(":kamel-image")) implementation(project(":kamel-tests")) + implementation(compose.material) } } @@ -94,11 +95,6 @@ kotlin { implementation(Dependencies.Android.ActivityCompose) implementation(Dependencies.Android.Material) implementation(Dependencies.Ktor.Android) - //todo: remove below when resolved https://github.com/JetBrains/compose-jb/issues/2238 - // the app will build without these imports. But Intellij highlights the compose - // imports in red if we do not add them here. (this is with the android 7.2 - // gradle plugin, 7.1 works correctly but causes lint errors when building) - implementation("androidx.compose.foundation:foundation:1.2.1") } } From c6f575591b00c171c2284c6295a8309c7f93c94a Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Mon, 12 Sep 2022 22:53:55 -0400 Subject: [PATCH 20/74] add iosSimulatorArm64 target --- buildSrc/src/main/kotlin/Targets.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Targets.kt b/buildSrc/src/main/kotlin/Targets.kt index 4599a58c..bb0a4a7c 100644 --- a/buildSrc/src/main/kotlin/Targets.kt +++ b/buildSrc/src/main/kotlin/Targets.kt @@ -1,7 +1,7 @@ object Targets { val iosTargets = arrayOf( - "iosArm64", "iosX64", + "iosArm64", "iosX64", "iosSimulatorArm64", ) val macosTargets = arrayOf( "macosX64", "macosArm64", From a448c2e5551f672036c65933b4aa5db8f3088b13 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Tue, 13 Sep 2022 02:42:25 -0400 Subject: [PATCH 21/74] ignore all build folders properly. do not ignore codestyles codestyles are set to kotlin official https://kotlinlang.org/docs/code-style-migration-guide.html --- .gitignore | 7 +++++-- .idea/codeStyles/Project.xml | 10 ++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 +++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml diff --git a/.gitignore b/.gitignore index ab6b7b48..e2c509f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ *.idea/* -*/build/* +build/ .gradle/* */.gradle/* local.properties *.iml *.gpg -*.DS_STORE \ No newline at end of file +*.DS_STORE + +# IntelliJ Code Styles +!/.idea/codeStyles/ \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..1bec35e5 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..79ee123c --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file From 8027009649679cb237be416f3fbda8c08f92bf68 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Tue, 13 Sep 2022 02:43:14 -0400 Subject: [PATCH 22/74] remove unused repos --- build.gradle.kts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ad1ec56e..36943cb0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,8 +11,6 @@ buildscript { mavenCentral() gradlePluginPortal() maven(url = "https://maven.pkg.jetbrains.space/public/p/compose/dev") - maven(url = "https://dl.bintray.com/kotlin/dokka") - maven(url = "https://kotlin.bintray.com/ktor") } dependencies { @@ -58,8 +56,6 @@ allprojects { google() mavenCentral() maven(url = "https://maven.pkg.jetbrains.space/public/p/compose/dev") - maven(url = "https://dl.bintray.com/kotlin/dokka") - maven(url = "https://kotlin.bintray.com/ktor") } val emptyJavadocJar by tasks.registering(Jar::class) { From 550f110441a01cb52cb2f6d065bb37d2e9d5bd56 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Tue, 13 Sep 2022 02:46:24 -0400 Subject: [PATCH 23/74] convert to suspend fun --- .../kotlin/io/kamel/tests/HttpMockEngine.kt | 8 ++++---- .../kotlin/io/kamel/tests/JvmTestUtils.kt | 20 +++++++++---------- .../kotlin/io/kamel/tests/JvmTestUtils.kt | 20 +++++++++---------- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/kamel-tests/src/commonMain/kotlin/io/kamel/tests/HttpMockEngine.kt b/kamel-tests/src/commonMain/kotlin/io/kamel/tests/HttpMockEngine.kt index 02cc2925..eb6c65f6 100644 --- a/kamel-tests/src/commonMain/kotlin/io/kamel/tests/HttpMockEngine.kt +++ b/kamel-tests/src/commonMain/kotlin/io/kamel/tests/HttpMockEngine.kt @@ -7,13 +7,13 @@ import io.ktor.utils.io.* val HttpMockEngine = MockEngine { request -> when (request.url.encodedPath) { "/emptyImage.jpg" -> respond(ByteReadChannel.Empty) - "/image.jpg" -> respond(resourceImage) - "/image.svg" -> respond(svgImage) + "/image.jpg" -> respond(resourceImage()) + "/image.svg" -> respond(svgImage()) else -> respondError(HttpStatusCode.NotFound) } } const val TestStringUrl = "https://www.example.com" -expect val resourceImage: ByteReadChannel -expect val svgImage: ByteReadChannel \ No newline at end of file +expect suspend fun resourceImage(): ByteReadChannel +expect suspend fun svgImage(): ByteReadChannel \ No newline at end of file diff --git a/kamel-tests/src/darwinMain/kotlin/io/kamel/tests/JvmTestUtils.kt b/kamel-tests/src/darwinMain/kotlin/io/kamel/tests/JvmTestUtils.kt index 5804f06f..76f78948 100644 --- a/kamel-tests/src/darwinMain/kotlin/io/kamel/tests/JvmTestUtils.kt +++ b/kamel-tests/src/darwinMain/kotlin/io/kamel/tests/JvmTestUtils.kt @@ -4,14 +4,12 @@ import io.ktor.utils.io.* import io.ktor.utils.io.core.* -actual val resourceImage: ByteReadChannel - get() { - val bytes = MR.files.Compose.readText().encodeToByteArray() - return ByteReadChannel(bytes) - } - -actual val svgImage: ByteReadChannel - get() { - val bytes = MR.files.Kotlin.readText().encodeToByteArray() - return ByteReadChannel(bytes) - } +actual suspend fun resourceImage(): ByteReadChannel { + val bytes = MR.files.Compose.readText().encodeToByteArray() + return ByteReadChannel(bytes) +} + +actual suspend fun svgImage(): ByteReadChannel { + val bytes = MR.files.Kotlin.readText().encodeToByteArray() + return ByteReadChannel(bytes) +} diff --git a/kamel-tests/src/jvmMain/kotlin/io/kamel/tests/JvmTestUtils.kt b/kamel-tests/src/jvmMain/kotlin/io/kamel/tests/JvmTestUtils.kt index f69d9602..0be87582 100644 --- a/kamel-tests/src/jvmMain/kotlin/io/kamel/tests/JvmTestUtils.kt +++ b/kamel-tests/src/jvmMain/kotlin/io/kamel/tests/JvmTestUtils.kt @@ -3,14 +3,12 @@ package io.kamel.tests import io.ktor.utils.io.* -actual val resourceImage: ByteReadChannel - get() { - val bytes = MR.files.Compose.readText().encodeToByteArray() - return ByteReadChannel(bytes) - } - -actual val svgImage: ByteReadChannel - get() { - val bytes = MR.files.Kotlin.readText().encodeToByteArray() - return ByteReadChannel(bytes) - } +actual suspend fun resourceImage(): ByteReadChannel { + val bytes = MR.files.Compose.readText().encodeToByteArray() + return ByteReadChannel(bytes) +} + +actual suspend fun svgImage(): ByteReadChannel { + val bytes = MR.files.Kotlin.readText().encodeToByteArray() + return ByteReadChannel(bytes) +} From 26c5fe83e03172fd2e87a41fe7a964e88f1fe894 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Tue, 13 Sep 2022 02:50:54 -0400 Subject: [PATCH 24/74] add js web support! --- .gitignore | 8 +- buildSrc/src/main/kotlin/Dependencies.kt | 1 + kamel-core/build.gradle.kts | 8 +- .../io/kamel/core/fetcher/FileFetcher.kt | 54 + .../kotlin/io/kamel/core/mapper/Mappers.kt | 25 + .../kotlin/io/kamel/core/utils/Platform.kt | 13 + kamel-image/build.gradle.kts | 11 +- kamel-samples/build.gradle.kts | 18 +- .../kotlin/io/kamel/samples/FileSample.kt | 53 + .../kotlin/io/kamel/samples/cellsCount.kt | 4 + kamel-samples/src/jsMain/kotlin/main.js.kt | 41 + kamel-samples/src/jsMain/resources/index.html | 15 + kamel-samples/src/jsMain/resources/styles.css | 8 + kamel-tests/build.gradle.kts | 4 +- .../kotlin/io/kamel/tests/JsTestUtils.kt | 13 + kotlin-js-store/yarn.lock | 2905 +++++++++++++++++ 16 files changed, 3175 insertions(+), 6 deletions(-) create mode 100644 kamel-core/src/jsMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt create mode 100644 kamel-core/src/jsMain/kotlin/io/kamel/core/mapper/Mappers.kt create mode 100644 kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt create mode 100644 kamel-samples/src/jsMain/kotlin/io/kamel/samples/FileSample.kt create mode 100644 kamel-samples/src/jsMain/kotlin/io/kamel/samples/cellsCount.kt create mode 100644 kamel-samples/src/jsMain/kotlin/main.js.kt create mode 100644 kamel-samples/src/jsMain/resources/index.html create mode 100644 kamel-samples/src/jsMain/resources/styles.css create mode 100644 kamel-tests/src/jsMain/kotlin/io/kamel/tests/JsTestUtils.kt create mode 100644 kotlin-js-store/yarn.lock diff --git a/.gitignore b/.gitignore index e2c509f7..bf916a71 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,10 @@ local.properties *.DS_STORE # IntelliJ Code Styles -!/.idea/codeStyles/ \ No newline at end of file +!/.idea/codeStyles/ + +# moko-resources-generated +kamel-tests/webpack.config.d/moko-resources-generated.js +kamel-tests/karma.config.d/moko-resources-generated.js +kamel-samples/webpack.config.d/moko-resources-generated.js +kamel-samples/karma.config.d/moko-resources-generated.js diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index da341762..41533c03 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -18,6 +18,7 @@ object Dependencies { const val Logging = "io.ktor:ktor-client-logging:${Versions.Ktor}" const val Android = "io.ktor:ktor-client-android:${Versions.Ktor}" const val Darwin = "io.ktor:ktor-client-darwin:${Versions.Ktor}" + const val Js = "io.ktor:ktor-client-js:${Versions.Ktor}" const val CIO = "io.ktor:ktor-client-cio:${Versions.Ktor}" } diff --git a/kamel-core/build.gradle.kts b/kamel-core/build.gradle.kts index b8d71526..c88c1a50 100644 --- a/kamel-core/build.gradle.kts +++ b/kamel-core/build.gradle.kts @@ -14,7 +14,9 @@ kotlin { explicitApi = ExplicitApiMode.Warning jvm() - + js(IR) { + browser() + } for (target in Targets.macosTargets) { targets.add( (presets.getByName(target).createTarget(target) as KotlinNativeTarget).apply { @@ -84,6 +86,10 @@ kotlin { dependsOn(commonTest) } + val jsMain by getting { + dependsOn(nonJvmMain) + } + val darwinMain by creating { dependsOn(nonJvmMain) } diff --git a/kamel-core/src/jsMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt b/kamel-core/src/jsMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt new file mode 100644 index 00000000..76b10ef1 --- /dev/null +++ b/kamel-core/src/jsMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt @@ -0,0 +1,54 @@ +package io.kamel.core.fetcher + +import io.kamel.core.DataSource +import io.kamel.core.Resource +import io.kamel.core.config.ResourceConfig +import io.kamel.core.utils.File +import io.ktor.utils.io.* +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.suspendCancellableCoroutine +import org.khronos.webgl.ArrayBuffer +import org.khronos.webgl.Int8Array +import org.w3c.dom.ErrorEvent +import org.w3c.files.FileReader +import kotlin.coroutines.resumeWithException +import kotlin.reflect.KClass + +/** + * Fetcher that fetchers [ByteReadChannel] from a file. + */ +internal actual object FileFetcher : Fetcher { + + override val inputDataKClass: KClass = File::class + + override val source: DataSource = DataSource.Disk + + override val File.isSupported: Boolean + get() = true + + @OptIn(ExperimentalCoroutinesApi::class) + override fun fetch( + data: File, + resourceConfig: ResourceConfig + ): Flow> = flow { + val byteReadChannel = ByteReadChannel(getBase64(data)) + emit(Resource.Success(byteReadChannel, source)) + } + + @ExperimentalCoroutinesApi + private suspend fun getBase64(file: org.w3c.files.File): ByteArray = suspendCancellableCoroutine { continuation -> + val reader = FileReader() + reader.readAsArrayBuffer(file) + reader.onload = { + val arrayBuffer = reader.result as ArrayBuffer + val bytes = Int8Array(arrayBuffer).unsafeCast() + continuation.resume(bytes, null) + } + reader.onerror = { error -> + continuation.resumeWithException(Error((error as ErrorEvent).message)) + } + } + +} \ No newline at end of file diff --git a/kamel-core/src/jsMain/kotlin/io/kamel/core/mapper/Mappers.kt b/kamel-core/src/jsMain/kotlin/io/kamel/core/mapper/Mappers.kt new file mode 100644 index 00000000..24780962 --- /dev/null +++ b/kamel-core/src/jsMain/kotlin/io/kamel/core/mapper/Mappers.kt @@ -0,0 +1,25 @@ +package io.kamel.core.mapper + +import io.kamel.core.utils.URI +import io.kamel.core.utils.URL +import io.ktor.http.* +import kotlin.reflect.KClass + +internal actual val URLMapper: Mapper = object : Mapper { + override val inputKClass: KClass + get() = URL::class + override val outputKClass: KClass + get() = Url::class + + override fun map(input: URL): Url = StringMapper.map(input.toString()) +} + + +internal actual val URIMapper: Mapper = object : Mapper { + override val inputKClass: KClass + get() = URI::class + override val outputKClass: KClass + get() = Url::class + + override fun map(input: URI): Url = StringMapper.map(input.uri) +} \ No newline at end of file diff --git a/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt new file mode 100644 index 00000000..d048851c --- /dev/null +++ b/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt @@ -0,0 +1,13 @@ +package io.kamel.core.utils + +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers + + +internal actual val Dispatchers.IO: CoroutineDispatcher get() = Default + +internal actual typealias File = org.w3c.files.File + +internal actual typealias URL = org.w3c.dom.url.URL + +public actual class URI(public val uri: String) \ No newline at end of file diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 45d19907..12aabc4e 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -55,7 +55,9 @@ kotlin { publishAllLibraryVariants() } jvm("desktop") - + js(IR) { + browser() + } for (target in Targets.nativeTargets) { targets.add(presets.getByName(target).createTarget(target)) } @@ -117,6 +119,13 @@ kotlin { dependsOn(commonTest) } + val jsMain by getting { + dependsOn(nonJvmMain) + dependencies { + implementation(Dependencies.Ktor.Js) + } + } + val darwinMain by creating { dependsOn(nonJvmMain) dependencies { diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index 3636ad97..dace5ed1 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -1,5 +1,6 @@ import org.jetbrains.compose.compose import org.jetbrains.compose.desktop.application.tasks.AbstractNativeMacApplicationPackageAppDirTask +import org.jetbrains.compose.experimental.dsl.IOSDevices import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractExecutable import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBinary @@ -11,6 +12,7 @@ import java.io.FileFilter plugins { multiplatform compose + mokoResources `android-application` } @@ -63,7 +65,10 @@ kotlin { android() jvm("desktop") - + js(IR) { + browser() + binaries.executable() + } for (target in Targets.macosTargets) { targets.add( (presets.getByName(target) @@ -77,7 +82,6 @@ kotlin { ) } - sourceSets { val commonMain by getting { @@ -125,6 +129,12 @@ kotlin { } } + +multiplatformResources { + multiplatformResourcesPackage = "io.kamel.samples" +} + + compose { desktop { application { @@ -133,6 +143,10 @@ compose { } } +compose.experimental { + web.application {} +} + compose.desktop.nativeApplication { targets(kotlin.targets.getByName("macosArm64")) diff --git a/kamel-samples/src/jsMain/kotlin/io/kamel/samples/FileSample.kt b/kamel-samples/src/jsMain/kotlin/io/kamel/samples/FileSample.kt new file mode 100644 index 00000000..271b4087 --- /dev/null +++ b/kamel-samples/src/jsMain/kotlin/io/kamel/samples/FileSample.kt @@ -0,0 +1,53 @@ +package io.kamel.samples + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import io.kamel.core.config.KamelConfig +import io.kamel.core.config.takeFrom +import io.kamel.image.KamelImage +import io.kamel.image.config.Default +import io.kamel.image.config.LocalKamelConfig +import io.kamel.image.config.imageVectorDecoder +import io.kamel.image.config.resourcesFetcher +import io.kamel.image.lazyPainterResource +import io.ktor.utils.io.core.* +import kotlinx.browser.window +import kotlinx.coroutines.await +import kotlinx.coroutines.launch +import org.w3c.files.File + +@Composable +internal fun FileSample() { + + val scope = rememberCoroutineScope() + var file: File? by remember { mutableStateOf(null) } + + scope.launch { + val blob = window.fetch(io.kamel.tests.MR.files.Compose.fileUrl).await().blob().await() + file = File( + arrayOf(blob), + io.kamel.tests.MR.files.Compose.fileUrl + ) + } + + val kamelConfig = KamelConfig { + takeFrom(KamelConfig.Default) + resourcesFetcher() + imageVectorDecoder() + } + + CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { + Column { + file?.let { file -> + val painterResource = lazyPainterResource(file) + KamelImage(painterResource, + contentDescription = "Compose", + modifier = Modifier.fillMaxSize(), + onFailure = { throw it }) + } + } + } +} diff --git a/kamel-samples/src/jsMain/kotlin/io/kamel/samples/cellsCount.kt b/kamel-samples/src/jsMain/kotlin/io/kamel/samples/cellsCount.kt new file mode 100644 index 00000000..f2b4dfd8 --- /dev/null +++ b/kamel-samples/src/jsMain/kotlin/io/kamel/samples/cellsCount.kt @@ -0,0 +1,4 @@ +package io.kamel.samples + + +public actual val cellsCount: Int = 4 diff --git a/kamel-samples/src/jsMain/kotlin/main.js.kt b/kamel-samples/src/jsMain/kotlin/main.js.kt new file mode 100644 index 00000000..08f11fec --- /dev/null +++ b/kamel-samples/src/jsMain/kotlin/main.js.kt @@ -0,0 +1,41 @@ +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.Button +import androidx.compose.material.Text +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.window.Window +import io.kamel.samples.FileSample +import io.kamel.samples.Gallery +import org.jetbrains.skiko.wasm.onWasmReady + +public fun main() { + onWasmReady { + Window("Sample") { + var sampleIndex by remember { mutableStateOf(0) } + Column(modifier = Modifier.fillMaxSize()) { + Row { + Button({ + sampleIndex = 0 + }) { + Text("Gallery") + } + Button({ + sampleIndex = 1 + }) { + Text("FileSample") + } + } + when (sampleIndex) { + 0 -> Gallery() + 1 -> FileSample() + else -> Text("Invalid Sample Index") + } + } + } + } +} \ No newline at end of file diff --git a/kamel-samples/src/jsMain/resources/index.html b/kamel-samples/src/jsMain/resources/index.html new file mode 100644 index 00000000..fd014742 --- /dev/null +++ b/kamel-samples/src/jsMain/resources/index.html @@ -0,0 +1,15 @@ + + + + + Kamel Samples + + + + +
+ +
+ + + \ No newline at end of file diff --git a/kamel-samples/src/jsMain/resources/styles.css b/kamel-samples/src/jsMain/resources/styles.css new file mode 100644 index 00000000..e5b3293a --- /dev/null +++ b/kamel-samples/src/jsMain/resources/styles.css @@ -0,0 +1,8 @@ +#root { + width: 100%; + height: 100vh; +} + +#root > .compose-web-column > div { + position: relative; +} \ No newline at end of file diff --git a/kamel-tests/build.gradle.kts b/kamel-tests/build.gradle.kts index 7dab709e..3abae161 100644 --- a/kamel-tests/build.gradle.kts +++ b/kamel-tests/build.gradle.kts @@ -5,6 +5,9 @@ plugins { kotlin { jvm() + js(IR) { + browser() + } for (target in Targets.nativeTargets) { targets.add(presets.getByName(target).createTarget(target)) } @@ -12,7 +15,6 @@ kotlin { sourceSets { val commonMain by getting { dependencies { - implementation(project(":kamel-core")) implementation(Dependencies.Testing.Ktor) implementation(Dependencies.Coroutines.Core) api(Dependencies.MokoResources.Core) diff --git a/kamel-tests/src/jsMain/kotlin/io/kamel/tests/JsTestUtils.kt b/kamel-tests/src/jsMain/kotlin/io/kamel/tests/JsTestUtils.kt new file mode 100644 index 00000000..31968b98 --- /dev/null +++ b/kamel-tests/src/jsMain/kotlin/io/kamel/tests/JsTestUtils.kt @@ -0,0 +1,13 @@ +package io.kamel.tests + +import io.ktor.utils.io.* + +actual suspend fun resourceImage(): ByteReadChannel { + val bytes = MR.files.Compose.getText().encodeToByteArray() + return ByteReadChannel(bytes) +} + +actual suspend fun svgImage(): ByteReadChannel { + val bytes = MR.files.Kotlin.getText().encodeToByteArray() + return ByteReadChannel(bytes) +} diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock new file mode 100644 index 00000000..aad19d39 --- /dev/null +++ b/kotlin-js-store/yarn.lock @@ -0,0 +1,2905 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.15" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" + integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" + integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + +"@messageformat/core@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@messageformat/core/-/core-3.0.0.tgz#8785c283218a11ced7f1474f547824bbce583f21" + integrity sha512-mzMCyADGweNmnMwV/xjKxtXtkXJNVcK5ATOHx4Q0GVr2Z3++in1VfrB/y6jM43nleK27tFO0Y/9pds5vxWqDvQ== + dependencies: + "@messageformat/date-skeleton" "^1.0.0" + "@messageformat/number-skeleton" "^1.0.0" + "@messageformat/parser" "^5.0.0" + "@messageformat/runtime" "^3.0.0" + make-plural "^6.2.1" + safe-identifier "^0.4.1" + +"@messageformat/date-skeleton@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@messageformat/date-skeleton/-/date-skeleton-1.0.1.tgz#980b8babe21a11433b6e1e8f6dc8c4cae4f5f56b" + integrity sha512-jPXy8fg+WMPIgmGjxSlnGJn68h/2InfT0TNSkVx0IGXgp4ynnvYkbZ51dGWmGySEK+pBiYUttbQdu5XEqX5CRg== + +"@messageformat/number-skeleton@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@messageformat/number-skeleton/-/number-skeleton-1.1.0.tgz#eb636738da8abbd35ccbeb84f7d84d63302aeb61" + integrity sha512-F0Io+GOSvFFxvp9Ze3L5kAoZ2NnOAT0Mr/jpGNd3fqo8A0t4NxNIAcCdggtl2B/gN2ErkIKSBVPrF7xcW1IGvA== + +"@messageformat/parser@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@messageformat/parser/-/parser-5.0.0.tgz#5737e69d7d4a469998b527710f1891174fc1b262" + integrity sha512-WiDKhi8F0zQaFU8cXgqq69eYFarCnTVxKcvhAONufKf0oUxbqLMW6JX6rV4Hqh+BEQWGyKKKHY4g1XA6bCLylA== + dependencies: + moo "^0.5.1" + +"@messageformat/runtime@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@messageformat/runtime/-/runtime-3.0.1.tgz#94d1f6c43265c28ef7aed98ecfcc0968c6c849ac" + integrity sha512-6RU5ol2lDtO8bD9Yxe6CZkl0DArdv0qkuoZC+ZwowU+cdRlVE1157wjCmlA5Rsf1Xc/brACnsZa5PZpEDfTFFg== + dependencies: + make-plural "^7.0.0" + +"@socket.io/component-emitter@~3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" + integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== + +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + +"@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + +"@types/cors@^2.8.12": + version "2.8.12" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" + integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== + +"@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.4.6" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.6.tgz#7976f054c1bccfcf514bff0564c0c41df5c08207" + integrity sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": + version "4.17.30" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz#0f2f99617fa8f9696170c46152ccf7500b34ac04" + integrity sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@*", "@types/express@^4.17.13": + version "4.17.13" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" + integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/http-proxy@^1.17.8": + version "1.17.9" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" + integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw== + dependencies: + "@types/node" "*" + +"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/mime@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== + +"@types/node@*", "@types/node@>=10.0.0": + version "18.7.17" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.17.tgz#52438111ea98f77475470fc62d79b9eb96bb2c92" + integrity sha512-0UyfUnt02zIuqp7yC8RYtDkp/vo8bFaQ13KkSEvUAohPOAlnVNbj5Fi3fgPSuwzakS+EvvnnZ4x9y7i6ASaSPQ== + +"@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/retry@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== + +"@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + +"@types/serve-static@*", "@types/serve-static@^1.13.10": + version "1.15.0" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155" + integrity sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg== + dependencies: + "@types/mime" "*" + "@types/node" "*" + +"@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" + +"@types/ws@^8.5.1": + version "8.5.3" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" + integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== + dependencies: + "@types/node" "*" + +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" + integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== + +"@webpack-cli/info@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" + integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" + integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +abab@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== + +abort-controller@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + +acorn@^8.4.1, acorn@^8.5.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" + integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.0, ajv@^8.8.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" + integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-flatten@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64id@2.0.0, base64id@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" + integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + +bcp-47@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/bcp-47/-/bcp-47-1.0.8.tgz#bf63ae4269faabe7c100deac0811121a48b6a561" + integrity sha512-Y9y1QNBBtYtv7hcmoX0tR+tUNSFZGZ6OL6vKPObq8BbOhkCoyayF6ogfLTgAli/KuAEbsYHYUNq2AQuY6IuLag== + dependencies: + is-alphabetical "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +body-parser@1.20.0, body-parser@^1.19.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" + integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.10.3" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +bonjour-service@^1.0.11: + version "1.0.14" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.0.14.tgz#c346f5bc84e87802d08f8d5a60b93f758e514ee7" + integrity sha512-HIMbgLnk1Vqvs6B4Wq5ep7mxvj9sGz5d1JJyDNSGNIdA/w2MCz6GTjWTdjqOJV1bEPj+6IkxDvWNFKEBxNt4kQ== + dependencies: + array-flatten "^2.1.2" + dns-equal "^1.0.0" + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserslist@^4.14.5: + version "4.21.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.3.tgz#5df277694eb3c48bc5c4b05af3e8b7e09c5a6d1a" + integrity sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ== + dependencies: + caniuse-lite "^1.0.30001370" + electron-to-chromium "^1.4.202" + node-releases "^2.0.6" + update-browserslist-db "^1.0.5" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001370: + version "1.0.30001397" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001397.tgz#010d9d56e3b8abcd8df261d0a94b22426271a15f" + integrity sha512-SW9N2TbCdLf0eiNDRrrQXx2sOkaakNZbCjgNpPyMJJbiOrU5QzMIrXOVMRM1myBXTD5iTkdrtU/EguCrBocHlA== + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@3.5.3, chokidar@^3.5.1, chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.10, colorette@^2.0.14: + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +connect-history-api-fallback@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" + integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== + +connect@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +cookie@~0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@~2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +custom-event@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" + integrity sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg== + +date-format@^4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.13.tgz#87c3aab3a4f6f37582c5f5f63692d2956fa67890" + integrity sha512-bnYCwf8Emc3pTD8pXnre+wfnjGtfi5ncMDKy7+cWZXbmRAsdWkOQHrfC1yz/KiwP5thDp2kCHWYWKBX4HP1hoQ== + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4.3.4, debug@^4.1.0, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== + dependencies: + execa "^5.0.0" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + +di@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" + integrity sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== + +dns-packet@^5.2.2: + version "5.4.0" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b" + integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + +dom-serialize@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" + integrity sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ== + dependencies: + custom-event "~1.0.0" + ent "~2.2.0" + extend "^3.0.0" + void-elements "^2.0.0" + +dukat@0.5.8-rc.4: + version "0.5.8-rc.4" + resolved "https://registry.yarnpkg.com/dukat/-/dukat-0.5.8-rc.4.tgz#90384dcb50b14c26f0e99dae92b2dea44f5fce21" + integrity sha512-ZnMt6DGBjlVgK2uQamXfd7uP/AxH7RqI0BL9GLrrJb2gKdDxvJChWy+M9AQEaL+7/6TmxzJxFOsRiInY9oGWTA== + dependencies: + google-protobuf "3.12.2" + typescript "3.9.5" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.202: + version "1.4.248" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.248.tgz#dd2dab68277e91e8452536ee9265f484066f94ad" + integrity sha512-qShjzEYpa57NnhbW2K+g+Fl+eNoDvQ7I+2MRwWnU6Z6F0HhXekzsECCLv+y2OJUsRodjqoSfwHkIX42VUFtUzg== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +engine.io-parser@~5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.4.tgz#0b13f704fa9271b3ec4f33112410d8f3f41d0fc0" + integrity sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg== + +engine.io@~6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.2.0.tgz#003bec48f6815926f2b1b17873e576acd54f41d0" + integrity sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg== + dependencies: + "@types/cookie" "^0.4.1" + "@types/cors" "^2.8.12" + "@types/node" ">=10.0.0" + accepts "~1.3.4" + base64id "2.0.0" + cookie "~0.4.1" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~5.0.3" + ws "~8.2.3" + +enhanced-resolve@^5.9.3: + version "5.10.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" + integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +ent@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + integrity sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA== + +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +express@^4.17.3: + version "4.18.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf" + integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.0" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.10.3" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +file-loader@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.2.6: + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + +follow-redirects@^1.0.0: + version "1.15.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" + integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== + +format-util@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.5.tgz#1ffb450c8a03e7bccffe40643180918cc297d271" + integrity sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg== + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-monkey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" + integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" + integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.3, glob@^7.1.7: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +google-protobuf@3.12.2: + version "3.12.2" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.12.2.tgz#50ce9f9b6281235724eb243d6a83e969a2176e53" + integrity sha512-4CZhpuRr1d6HjlyrxoXoocoGFnRYgKULgMtikMddA9ztRyYR59Aondv2FioyxWVamRo0rF2XpYawkTCBEQOSkA== + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +html-entities@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" + integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + +http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.9.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" + integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== + dependencies: + has "^1.0.3" + +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isbinaryfile@^4.0.8: + version "4.0.10" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" + integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json5@^2.1.2: + version "2.2.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== + optionalDependencies: + graceful-fs "^4.1.6" + +karma-chrome-launcher@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz#baca9cc071b1562a1db241827257bfe5cab597ea" + integrity sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ== + dependencies: + which "^1.2.1" + +karma-mocha@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-2.0.1.tgz#4b0254a18dfee71bdbe6188d9a6861bf86b0cd7d" + integrity sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ== + dependencies: + minimist "^1.2.3" + +karma-sourcemap-loader@0.3.8: + version "0.3.8" + resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.8.tgz#d4bae72fb7a8397328a62b75013d2df937bdcf9c" + integrity sha512-zorxyAakYZuBcHRJE+vbrK2o2JXLFWK8VVjiT/6P+ltLBUGUvqTEkUiQ119MGdOrK7mrmxXHZF1/pfT6GgIZ6g== + dependencies: + graceful-fs "^4.1.2" + +karma-webpack@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-5.0.0.tgz#2a2c7b80163fe7ffd1010f83f5507f95ef39f840" + integrity sha512-+54i/cd3/piZuP3dr54+NcFeKOPnys5QeM1IY+0SPASwrtHsliXUiCL50iW+K9WWA7RvamC4macvvQ86l3KtaA== + dependencies: + glob "^7.1.3" + minimatch "^3.0.4" + webpack-merge "^4.1.5" + +karma@6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.0.tgz#82652dfecdd853ec227b74ed718a997028a99508" + integrity sha512-s8m7z0IF5g/bS5ONT7wsOavhW4i4aFkzD4u4wgzAQWT4HGUeWI3i21cK2Yz6jndMAeHETp5XuNsRoyGJZXVd4w== + dependencies: + "@colors/colors" "1.5.0" + body-parser "^1.19.0" + braces "^3.0.2" + chokidar "^3.5.1" + connect "^3.7.0" + di "^0.0.1" + dom-serialize "^2.2.1" + glob "^7.1.7" + graceful-fs "^4.2.6" + http-proxy "^1.18.1" + isbinaryfile "^4.0.8" + lodash "^4.17.21" + log4js "^6.4.1" + mime "^2.5.2" + minimatch "^3.0.4" + mkdirp "^0.5.5" + qjobs "^1.2.0" + range-parser "^1.2.1" + rimraf "^3.0.2" + socket.io "^4.4.1" + source-map "^0.6.1" + tmp "^0.2.1" + ua-parser-js "^0.7.30" + yargs "^16.1.1" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +loader-utils@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" + integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash@^4.17.15, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +log4js@^6.4.1: + version "6.6.1" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.6.1.tgz#48f23de8a87d2f5ffd3d913f24ca9ce77895272f" + integrity sha512-J8VYFH2UQq/xucdNu71io4Fo+purYYudyErgBbswWKO0MC6QVOERRomt5su/z6d3RJSmLyTGmXl3Q/XjKCf+/A== + dependencies: + date-format "^4.0.13" + debug "^4.3.4" + flatted "^3.2.6" + rfdc "^1.3.0" + streamroller "^3.1.2" + +make-plural@^6.2.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-6.2.2.tgz#beb5fd751355e72660eeb2218bb98eec92853c6c" + integrity sha512-8iTuFioatnTTmb/YJjywkVIHLjcwkFD9Ms0JpxjEm9Mo8eQYkh1z+55dwv4yc1jQ8ftVBxWQbihvZL1DfzGGWA== + +make-plural@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-7.1.0.tgz#8a0381ff8c9be4f074e0acdc42ec97639c2344f9" + integrity sha512-PKkwVlAxYVo98NrbclaQIT4F5Oy+X58PZM5r2IwUSCe3syya6PXkIRCn2XCdz7p58Scgpp50PBeHmepXVDG3hg== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memfs@^3.4.3: + version "3.4.7" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.7.tgz#e5252ad2242a724f938cb937e3c4f7ceb1f70e5a" + integrity sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw== + dependencies: + fs-monkey "^1.0.3" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +micromatch@^4.0.2: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mime@^2.5.2: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimalistic-assert@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.3, minimist@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +mkdirp@^0.5.5: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mocha@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.0.0.tgz#205447d8993ec755335c4b13deba3d3a13c4def9" + integrity sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +moo@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4" + integrity sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== + dependencies: + dns-packet "^5.2.2" + thunky "^1.0.2" + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + +node-releases@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +object-assign@^4: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +open@^8.0.9: + version "8.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" + integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-retry@^4.5.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== + dependencies: + "@types/retry" "0.12.0" + retry "^0.13.1" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qjobs@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" + integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== + +qs@6.10.3: + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + dependencies: + side-channel "^1.0.4" + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +readable-stream@^2.0.1: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.9.0: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-identifier@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/safe-identifier/-/safe-identifier-0.4.2.tgz#cf6bfca31c2897c588092d1750d30ef501d59fcb" + integrity sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w== + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + +selfsigned@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" + integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== + dependencies: + node-forge "^1" + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@6.0.0, serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +socket.io-adapter@~2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz#b50a4a9ecdd00c34d4c8c808224daa1a786152a6" + integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg== + +socket.io-parser@~4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.1.tgz#01c96efa11ded938dcb21cbe590c26af5eff65e5" + integrity sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + +socket.io@^4.4.1: + version "4.5.2" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.5.2.tgz#1eb25fd380ab3d63470aa8279f8e48d922d443ac" + integrity sha512-6fCnk4ARMPZN448+SQcnn1u8OHUC72puJcNtSgg2xS34Cu7br1gQ09YKkO1PFfDn/wyUE9ZgMAwosJed003+NQ== + dependencies: + accepts "~1.3.4" + base64id "~2.0.0" + debug "~4.3.2" + engine.io "~6.2.0" + socket.io-adapter "~2.4.0" + socket.io-parser "~4.2.0" + +sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map-loader@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-4.0.0.tgz#bdc6b118bc6c87ee4d8d851f2d4efcc5abdb2ef5" + integrity sha512-i3KVgM3+QPAHNbGavK+VBq03YoJl24m9JWNbLgsjTj8aJzXG9M61bantBTNBt7CNwY2FYf+RJRYJ3pzalKjIrw== + dependencies: + abab "^2.0.6" + iconv-lite "^0.6.3" + source-map-js "^1.0.2" + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +streamroller@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.2.tgz#abd444560768b340f696307cf84d3f46e86c0e63" + integrity sha512-wZswqzbgGGsXYIrBYhOE0yP+nQ6XRk7xDcYwuQAGTYXdyAUmvgVFE0YU1g5pvQT0m7GBaQfYcSnlHbapuK0H0A== + dependencies: + date-format "^4.0.13" + debug "^4.3.4" + fs-extra "^8.1.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@8.1.1, supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.1.3: + version "5.3.6" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" + integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== + dependencies: + "@jridgewell/trace-mapping" "^0.3.14" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" + terser "^5.14.1" + +terser@^5.14.1: + version "5.15.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.0.tgz#e16967894eeba6e1091509ec83f0c60e179f2425" + integrity sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +tmp@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typescript@3.9.5: + version "3.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" + integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== + +ua-parser-js@^0.7.30: + version "0.7.31" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6" + integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ== + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.0.5: + version "1.0.8" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.8.tgz#2f0b711327668eee01bbecddcf4a7c7954a7f8e2" + integrity sha512-GHg7C4M7oJSJYW/ED/5QOJ7nL/E0lwTOBGsOorA7jqHr8ExUhPfwAotIAmdSw/LWv3SMLSNpzTAgeLG9zaZKTA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url-loader@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" + integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== + dependencies: + loader-utils "^2.0.0" + mime-types "^2.1.27" + schema-utils "^3.0.0" + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" + integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== + +watchpack@^2.3.1: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webpack-cli@4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" + integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.2.0" + "@webpack-cli/info" "^1.5.0" + "@webpack-cli/serve" "^1.7.0" + colorette "^2.0.14" + commander "^7.0.0" + cross-spawn "^7.0.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + +webpack-dev-middleware@^5.3.1: + version "5.3.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" + integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== + dependencies: + colorette "^2.0.10" + memfs "^3.4.3" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-dev-server@4.9.2: + version "4.9.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.9.2.tgz#c188db28c7bff12f87deda2a5595679ebbc3c9bc" + integrity sha512-H95Ns95dP24ZsEzO6G9iT+PNw4Q7ltll1GfJHV4fKphuHWgKFzGHWi4alTlTnpk1SPPk41X+l2RB7rLfIhnB9Q== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/serve-static" "^1.13.10" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.5.1" + ansi-html-community "^0.0.8" + bonjour-service "^1.0.11" + chokidar "^3.5.3" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^1.6.0" + default-gateway "^6.0.3" + express "^4.17.3" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.3" + ipaddr.js "^2.0.1" + open "^8.0.9" + p-retry "^4.5.0" + rimraf "^3.0.2" + schema-utils "^4.0.0" + selfsigned "^2.0.1" + serve-index "^1.9.1" + sockjs "^0.3.24" + spdy "^4.0.2" + webpack-dev-middleware "^5.3.1" + ws "^8.4.2" + +webpack-merge@^4.1.5: + version "4.2.2" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" + integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== + dependencies: + lodash "^4.17.15" + +webpack-merge@^5.7.3: + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@5.73.0: + version "5.73.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.73.0.tgz#bbd17738f8a53ee5760ea2f59dce7f3431d35d38" + integrity sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.4.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.9.3" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.3.1" + webpack-sources "^3.2.3" + +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which@^1.2.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + +ws@^8.4.2: + version "8.8.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0" + integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA== + +ws@~8.2.3: + version "8.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" + integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0, yargs@^16.1.1: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 6c152bf253be16e5f385249a26e429ed0bb6f22d Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Tue, 13 Sep 2022 02:51:09 -0400 Subject: [PATCH 25/74] cleanup/refactor --- .../kotlin/io/kamel/core/fetcher/FileFetcher.kt | 8 ++------ .../kotlin/io/kamel/core/utils/ConfigUtils.kt | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) rename kamel-core/src/{darwinMain => nonJvmMain}/kotlin/io/kamel/core/utils/ConfigUtils.kt (97%) diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt index 23a5d8a6..67b964a2 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt @@ -5,12 +5,8 @@ import io.kamel.core.Resource import io.kamel.core.config.ResourceConfig import io.kamel.core.utils.File import io.ktor.utils.io.* -import kotlinx.cinterop.addressOf -import kotlinx.cinterop.usePinned import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow -import platform.Foundation.NSData -import platform.posix.memcpy import kotlin.reflect.KClass /** @@ -29,8 +25,8 @@ internal actual object FileFetcher : Fetcher { data: File, resourceConfig: ResourceConfig ): Flow> = flow { - val bytes = ByteReadChannel(data.availableData) - emit(Resource.Success(bytes, source)) + val byteReadChannel = ByteReadChannel(data.availableData) + emit(Resource.Success(byteReadChannel, source)) } } \ No newline at end of file diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/ConfigUtils.kt b/kamel-core/src/nonJvmMain/kotlin/io/kamel/core/utils/ConfigUtils.kt similarity index 97% rename from kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/ConfigUtils.kt rename to kamel-core/src/nonJvmMain/kotlin/io/kamel/core/utils/ConfigUtils.kt index 00ef61f3..7ae031e8 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/ConfigUtils.kt +++ b/kamel-core/src/nonJvmMain/kotlin/io/kamel/core/utils/ConfigUtils.kt @@ -5,7 +5,6 @@ package io.kamel.core.utils import io.kamel.core.config.KamelConfig import io.kamel.core.decoder.Decoder import io.kamel.core.fetcher.Fetcher -import kotlin.reflect.typeOf internal actual fun KamelConfig.findFetcherFor(data: T): Fetcher { From c7cc393db1c7e5f2aa6714a48e88f8c0c3453849 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Tue, 13 Sep 2022 03:08:44 -0400 Subject: [PATCH 26/74] implement MappersUtils for js. move HttpFetcherTest to common. --- .../io/kamel/core/fetcher/HttpFetcherTest.kt | 0 .../io/kamel/core/utils/MappersUtils.kt | 7 ++ .../io/kamel/core/fetcher/HttpFetcherTest.kt | 72 ------------------- 3 files changed, 7 insertions(+), 72 deletions(-) rename kamel-core/src/{darwinTest => commonTest}/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt (100%) create mode 100644 kamel-core/src/jsTest/kotlin/io/kamel/core/utils/MappersUtils.kt delete mode 100644 kamel-core/src/jvmTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt diff --git a/kamel-core/src/darwinTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt b/kamel-core/src/commonTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt similarity index 100% rename from kamel-core/src/darwinTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt rename to kamel-core/src/commonTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt diff --git a/kamel-core/src/jsTest/kotlin/io/kamel/core/utils/MappersUtils.kt b/kamel-core/src/jsTest/kotlin/io/kamel/core/utils/MappersUtils.kt new file mode 100644 index 00000000..8f70f5e2 --- /dev/null +++ b/kamel-core/src/jsTest/kotlin/io/kamel/core/utils/MappersUtils.kt @@ -0,0 +1,7 @@ +package io.kamel.core.utils + + + +internal actual fun createURL(url: String): URL = URL(url) + +internal actual fun createURI(url: String): URI = URI(url) \ No newline at end of file diff --git a/kamel-core/src/jvmTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt b/kamel-core/src/jvmTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt deleted file mode 100644 index 333f1040..00000000 --- a/kamel-core/src/jvmTest/kotlin/io/kamel/core/fetcher/HttpFetcherTest.kt +++ /dev/null @@ -1,72 +0,0 @@ -package io.kamel.core.fetcher - -import io.kamel.core.DataSource -import io.kamel.core.config.ResourceConfig -import io.kamel.core.config.ResourceConfigBuilder -import io.kamel.core.getOrNull -import io.kamel.core.isLoading -import io.kamel.core.map -import io.kamel.tests.HttpMockEngine -import io.ktor.client.* -import io.ktor.http.* -import io.ktor.util.* -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.test.runTest -import kotlin.test.Test -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -@OptIn(ExperimentalCoroutinesApi::class) -class HttpFetcherTest { - - private val fetcher: HttpFetcher = HttpFetcher(HttpClient(HttpMockEngine)) - private val resourceConfig: ResourceConfig = ResourceConfigBuilder().build() - - @Test - fun testWebSocketUrlIsSupported() = runTest { - val urlBuilder = URLBuilder(protocol = URLProtocol.WS) - val isSupported = with(fetcher) { Url(urlBuilder).isSupported } - - assertFalse { isSupported } - } - - @Test - fun testHttpUrlIsSupported() = runTest { - val urlBuilder = URLBuilder(protocol = URLProtocol.HTTP) - val isSupported = with(fetcher) { Url(urlBuilder).isSupported } - - assertTrue { isSupported } - } - - @Test - fun testHttpsUrlIsSupported() = runTest { - val urlBuilder = URLBuilder(protocol = URLProtocol.HTTPS) - val isSupported = with(fetcher) { Url(urlBuilder).isSupported } - - assertTrue { isSupported } - } - - @Test - fun testFetchingEmptyImageBytes(): Unit = runTest { - val url = Url("/emptyImage.jpg") - val resource = fetcher.fetch(url, resourceConfig) - .first { !it.isLoading } - .map { it.toByteArray() } - - assertTrue { resource.getOrNull()!!.isEmpty() } - assertTrue { resource.source == DataSource.Network } - } - - @Test - fun testFetchingNonEmptyImageBytes(): Unit = runTest { - val url = Url("/image.svg") - val resource = fetcher.fetch(url, resourceConfig) - .first { !it.isLoading } - .map { it.toByteArray() } - - assertTrue { resource.getOrNull()!!.isNotEmpty() } - assertTrue { resource.source == DataSource.Network } - } - -} \ No newline at end of file From a642b6b5749b72212f998fe9e0dc20d1e346f5bf Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Thu, 29 Sep 2022 17:17:20 -0400 Subject: [PATCH 27/74] update agp. Working in latest intellij eap! --- buildSrc/src/main/kotlin/Dependencies.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 41533c03..3b6f6bad 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -46,7 +46,7 @@ object Versions { const val Ktor = "2.0.3" const val Coroutines = "1.6.4" const val Compose = "1.2.0-alpha01-dev778" - const val AGP = "7.3.0-rc01" + const val AGP = "7.3.0" const val MokoResources = "0.20.1" object Android { From a358b6d28ad4a67ec14034fde2dd41d2af03835a Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Thu, 29 Sep 2022 17:18:50 -0400 Subject: [PATCH 28/74] don't leak compose dependencies as api --- kamel-core/build.gradle.kts | 6 +++--- kamel-image/build.gradle.kts | 3 +++ kamel-samples/build.gradle.kts | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/kamel-core/build.gradle.kts b/kamel-core/build.gradle.kts index c88c1a50..b4cfebdb 100644 --- a/kamel-core/build.gradle.kts +++ b/kamel-core/build.gradle.kts @@ -52,9 +52,9 @@ kotlin { val commonMain by getting { dependencies { - api(compose.ui) - api(compose.foundation) - api(compose.runtime) + implementation(compose.ui) + implementation(compose.foundation) + implementation(compose.runtime) api(Dependencies.Ktor.Core) } } diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 12aabc4e..a11c2d3e 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -67,6 +67,9 @@ kotlin { val commonMain by getting { dependencies { api(project(":kamel-core")) + implementation(compose.ui) + implementation(compose.foundation) + implementation(compose.runtime) } } diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index dace5ed1..3bcedfb1 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -88,6 +88,7 @@ kotlin { dependencies { implementation(project(":kamel-image")) implementation(project(":kamel-tests")) + implementation(compose.foundation) implementation(compose.material) } } From 545568624cbe3f617273b30fb4ade530ee8cb96a Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Tue, 4 Oct 2022 15:50:34 -0400 Subject: [PATCH 29/74] add ios sample --- kamel-samples/build.gradle.kts | 64 ++++++++++++++++++- .../io/kamel/samples/darwinCellsCount.kt | 4 ++ .../io/kamel/samples/darwinFileSample.kt} | 1 - .../kotlin/io/kamel/samples/launcher.kt | 34 ++++++++++ .../kotlin/io/kamel/samples/cellsCount.kt | 8 --- .../src/macosMain/kotlin/main.macos.kt | 32 +--------- .../src/uikitMain/kotlin/main.uikit.kt | 47 ++++++++++++++ 7 files changed, 148 insertions(+), 42 deletions(-) create mode 100644 kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinCellsCount.kt rename kamel-samples/src/{macosMain/kotlin/io/kamel/samples/FileSample.kt => darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt} (94%) create mode 100644 kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt delete mode 100644 kamel-samples/src/macosMain/kotlin/io/kamel/samples/cellsCount.kt create mode 100644 kamel-samples/src/uikitMain/kotlin/main.uikit.kt diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index 3bcedfb1..535d3f3f 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -1,13 +1,14 @@ import org.jetbrains.compose.compose import org.jetbrains.compose.desktop.application.tasks.AbstractNativeMacApplicationPackageAppDirTask -import org.jetbrains.compose.experimental.dsl.IOSDevices import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractExecutable import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBinary import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink import org.jetbrains.kotlin.library.impl.KotlinLibraryLayoutImpl -import org.jetbrains.kotlin.konan.file.File as KonanFile +import java.io.File import java.io.FileFilter +import org.jetbrains.compose.experimental.dsl.IOSDevices as IOSDevices1 +import org.jetbrains.kotlin.konan.file.File as KonanFile plugins { multiplatform @@ -81,6 +82,22 @@ kotlin { } ) } + for (target in Targets.iosTargets) { + targets.add( + (presets.getByName(target) + .createTarget(target.replace("ios", "uikit")) + as org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget).apply { + binaries.executable { + entryPoint = "main" + freeCompilerArgs += listOf( + "-linker-option", "-framework", "-linker-option", "Metal", + "-linker-option", "-framework", "-linker-option", "CoreText", + "-linker-option", "-framework", "-linker-option", "CoreGraphics" + ) + } + } + ) + } sourceSets { @@ -111,16 +128,32 @@ kotlin { } } - val macosMain by creating { + val darwinMain by creating { dependsOn(commonMain) } + val macosMain by creating { + dependsOn(darwinMain) + } + Targets.macosTargets.forEach { target -> getByName("${target}Main") { dependsOn(macosMain) } } + val uikitMain by creating { + dependsOn(darwinMain) + } + + Targets.iosTargets.map { target -> + target.replace("ios", "uikit") + }.forEach { target -> + getByName("${target}Main") { + dependsOn(uikitMain) + } + } + all { languageSettings.apply { optIn("kotlin.Experimental") @@ -146,6 +179,25 @@ compose { compose.experimental { web.application {} + uikit.application { + bundleIdPrefix = "io.kamel.samples" + projectName = "kamel samples" + deployConfigurations { + simulator("IPhone13") { + //Usage: ./gradlew iosDeployIPhone8Debug + device = IOSDevices1.IPHONE_13 + } + simulator("IPad") { + //Usage: ./gradlew iosDeployIPadDebug + device = IOSDevices1.IPAD_PRO_11_INCH_3rd_Gen + } + connectedDevice("Device") { + //First need specify your teamId here, or in local.properties (compose.ios.teamId=***) + //teamId="***" + //Usage: ./gradlew iosDeployDeviceRelease + } + } + } } @@ -158,6 +210,12 @@ compose.desktop.nativeApplication { } } +// TODO: remove when https://youtrack.jetbrains.com/issue/KT-50778 fixed +project.tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile::class.java).configureEach { + kotlinOptions.freeCompilerArgs += listOf( + "-Xir-dce-runtime-diagnostic=log" + ) +} // todo: Remove when resolved: https://github.com/icerockdev/moko-resources/issues/372 tasks.withType() diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinCellsCount.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinCellsCount.kt new file mode 100644 index 00000000..f2b4dfd8 --- /dev/null +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinCellsCount.kt @@ -0,0 +1,4 @@ +package io.kamel.samples + + +public actual val cellsCount: Int = 4 diff --git a/kamel-samples/src/macosMain/kotlin/io/kamel/samples/FileSample.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt similarity index 94% rename from kamel-samples/src/macosMain/kotlin/io/kamel/samples/FileSample.kt rename to kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt index 2f5e71e2..94078f48 100644 --- a/kamel-samples/src/macosMain/kotlin/io/kamel/samples/FileSample.kt +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt @@ -2,7 +2,6 @@ package io.kamel.samples import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.Text import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import io.kamel.core.ExperimentalKamelApi diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt new file mode 100644 index 00000000..76600dca --- /dev/null +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt @@ -0,0 +1,34 @@ +package io.kamel.samples + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.material.Button +import androidx.compose.material.Text +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue + +@androidx.compose.runtime.Composable +public fun launcher(){ + var sampleIndex by remember { mutableStateOf(0) } + Column { + Row { + Button({ + sampleIndex = 0 + }) { + Text("Gallery") + } + Button({ + sampleIndex = 1 + }) { + Text("FileSample") + } + } + when (sampleIndex) { + 0 -> Gallery() + 1 -> FileSample() + else -> Text("Invalid Sample Index") + } + } +} \ No newline at end of file diff --git a/kamel-samples/src/macosMain/kotlin/io/kamel/samples/cellsCount.kt b/kamel-samples/src/macosMain/kotlin/io/kamel/samples/cellsCount.kt deleted file mode 100644 index f405dd5a..00000000 --- a/kamel-samples/src/macosMain/kotlin/io/kamel/samples/cellsCount.kt +++ /dev/null @@ -1,8 +0,0 @@ -package io.kamel.samples - -import androidx.compose.ui.window.Window -import platform.AppKit.NSApp -import platform.AppKit.NSApplication - - -public actual val cellsCount: Int = 4 diff --git a/kamel-samples/src/macosMain/kotlin/main.macos.kt b/kamel-samples/src/macosMain/kotlin/main.macos.kt index 18163e2a..25a086c0 100644 --- a/kamel-samples/src/macosMain/kotlin/main.macos.kt +++ b/kamel-samples/src/macosMain/kotlin/main.macos.kt @@ -1,40 +1,12 @@ -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.material.Button -import androidx.compose.material.Text -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.window.Window -import io.kamel.samples.FileSample -import io.kamel.samples.Gallery +import io.kamel.samples.launcher import platform.AppKit.NSApp import platform.AppKit.NSApplication public fun main() { NSApplication.sharedApplication() Window("Sample") { - var sampleIndex by remember { mutableStateOf(0) } - Column { - Row { - Button({ - sampleIndex = 0 - }) { - Text("Gallery") - } - Button({ - sampleIndex = 1 - }) { - Text("FileSample") - } - } - when (sampleIndex) { - 0 -> Gallery() - 1 -> FileSample() - else -> Text("Invalid Sample Index") - } - } + launcher() } NSApp?.run() } \ No newline at end of file diff --git a/kamel-samples/src/uikitMain/kotlin/main.uikit.kt b/kamel-samples/src/uikitMain/kotlin/main.uikit.kt new file mode 100644 index 00000000..6e0e9e0d --- /dev/null +++ b/kamel-samples/src/uikitMain/kotlin/main.uikit.kt @@ -0,0 +1,47 @@ +import androidx.compose.ui.window.Application +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.ui.unit.dp +import androidx.compose.ui.Modifier +import io.kamel.samples.launcher +import kotlinx.cinterop.autoreleasepool +import kotlinx.cinterop.cstr +import kotlinx.cinterop.memScoped +import kotlinx.cinterop.toCValues +import platform.Foundation.NSStringFromClass +import platform.UIKit.* + +fun main() { + val args = emptyArray() + memScoped { + val argc = args.size + 1 + val argv = (arrayOf("skikoApp") + args).map { it.cstr.ptr }.toCValues() + autoreleasepool { + UIApplicationMain(argc, argv, null, NSStringFromClass(SkikoAppDelegate)) + } + } +} + +class SkikoAppDelegate : UIResponder, UIApplicationDelegateProtocol { + companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta + + @OverrideInit + constructor() : super() + + private var _window: UIWindow? = null + override fun window() = _window + override fun setWindow(window: UIWindow?) { + _window = window + } + + override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map?): Boolean { + window = UIWindow(frame = UIScreen.mainScreen.bounds) + window!!.rootViewController = Application("Sample") { + Column(Modifier.padding(top = 30.dp)) { + launcher() + } + } + window!!.makeKeyAndVisible() + return true + } +} From cea3c71fd7302b23a8ac64ed80a15e783c71a99e Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Fri, 2 Dec 2022 21:41:47 -0500 Subject: [PATCH 30/74] update kotlin, compose, and agp --- buildSrc/src/main/kotlin/Dependencies.kt | 6 +++--- gradle.properties | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 3b6f6bad..1437dfbf 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -42,11 +42,11 @@ object Dependencies { object Versions { - const val Kotlin = "1.7.10" + const val Kotlin = "1.7.20" const val Ktor = "2.0.3" const val Coroutines = "1.6.4" - const val Compose = "1.2.0-alpha01-dev778" - const val AGP = "7.3.0" + const val Compose = "1.2.1" + const val AGP = "7.3.1" const val MokoResources = "0.20.1" object Android { diff --git a/gradle.properties b/gradle.properties index 893c578b..f552389c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,6 @@ org.gradle.jvmargs=-Xmx3g kotlin.code.style=official kotlin.native.cacheKind=none kotlin.native.useEmbeddableCompilerJar=true -kotlin.native.binary.memoryModel=experimental kotlin.mpp.enableCInteropCommonization=true compose.desktop.verbose=true android.useAndroidX=true From 1da307b34251bb3aaa7fe0438ab26966e7adb23e Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sat, 6 May 2023 00:42:02 -0400 Subject: [PATCH 31/74] update to kotlin 1.8.20, and compose 1.40 --- buildSrc/src/main/kotlin/Dependencies.kt | 22 +- gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 60756 bytes gradle/wrapper/gradle-wrapper.properties | 5 +- gradlew | 263 +++++++++++------- gradlew.bat | 14 +- .../kotlin/io/kamel/core/utils/Platform.kt | 2 +- .../io/kamel/image/LazyPainterResource.kt | 4 +- 7 files changed, 183 insertions(+), 127 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 1437dfbf..189b2683 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -42,19 +42,19 @@ object Dependencies { object Versions { - const val Kotlin = "1.7.20" - const val Ktor = "2.0.3" - const val Coroutines = "1.6.4" - const val Compose = "1.2.1" - const val AGP = "7.3.1" - const val MokoResources = "0.20.1" + const val Kotlin = "1.8.20" + const val Ktor = "2.3.0" + const val Coroutines = "1.7.0" + const val Compose = "1.4.0" + const val AGP = "7.4.2" + const val MokoResources = "0.22.0" object Android { - const val ActivityCompose = "1.5.1" - const val Appcompat = "1.4.2" - const val Material = "1.6.1" - const val Annotation = "1.4.0" - const val UIGraphics = "1.2.1" + const val ActivityCompose = "1.7.1" + const val Appcompat = "1.6.1" + const val Material = "1.8.0" + const val Annotation = "1.6.0" + const val UIGraphics = "1.4.3" } } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..249e5832f090a2944b7473328c07c9755baa3196 100644 GIT binary patch delta 21931 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 delta 20228 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,101 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index ac1b06f9..53a6b238 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt index 81a1c602..7c270864 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt @@ -11,7 +11,7 @@ import platform.Foundation.fileHandleForReadingAtPath import platform.posix.memcpy -internal actual val Dispatchers.IO: CoroutineDispatcher get() = Default +internal actual val Dispatchers.IO: CoroutineDispatcher get() = Dispatchers.Default public actual class File(public val path: String) { diff --git a/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt b/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt index 3a32603c..49f9d57a 100644 --- a/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt +++ b/kamel-image/src/commonMain/kotlin/io/kamel/image/LazyPainterResource.kt @@ -40,7 +40,7 @@ public inline fun lazyPainterResource( filterQuality: FilterQuality = DrawScope.DefaultFilterQuality, noinline onLoadingPainter: @Composable (Float) -> Result = { Result.failure(PainterFailure()) }, noinline onFailurePainter: @Composable (Throwable) -> Result = { Result.failure(PainterFailure()) }, - block: ResourceConfigBuilder.() -> Unit = {}, + crossinline block: ResourceConfigBuilder.() -> Unit = {}, ): Resource { val kamelConfig = LocalKamelConfig.current @@ -104,7 +104,7 @@ public inline fun lazyPainterResource( data: Any, key: Any? = data, filterQuality: FilterQuality = DrawScope.DefaultFilterQuality, - block: ResourceConfigBuilder.() -> Unit = {}, + crossinline block: ResourceConfigBuilder.() -> Unit = {}, ): Resource = lazyPainterResource( data, key, From 30d445f2459c01af0e00d73356c16117e3dc5407 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sat, 6 May 2023 01:43:19 -0400 Subject: [PATCH 32/74] fix signing when publishing --- buildSrc/src/main/kotlin/Plugins.kt | 2 +- kamel-core/build.gradle.kts | 7 + kamel-image/build.gradle.kts | 7 + kotlin-js-store/yarn.lock | 498 ++++++++++++++++++++++++---- 4 files changed, 444 insertions(+), 70 deletions(-) diff --git a/buildSrc/src/main/kotlin/Plugins.kt b/buildSrc/src/main/kotlin/Plugins.kt index 5b7220a1..b95322ea 100644 --- a/buildSrc/src/main/kotlin/Plugins.kt +++ b/buildSrc/src/main/kotlin/Plugins.kt @@ -13,7 +13,7 @@ inline val PluginDependenciesSpec.mokoResources: PluginDependencySpec get() = id("dev.icerock.mobile.multiplatform-resources") version Versions.MokoResources inline val PluginDependenciesSpec.`nexus-staging`: PluginDependencySpec - get() = id("io.codearte.nexus-staging") version "0.22.0" + get() = id("io.codearte.nexus-staging") version "0.30.0" inline val PluginDependenciesSpec.`android-library`: PluginDependencySpec get() = id("com.android.library") diff --git a/kamel-core/build.gradle.kts b/kamel-core/build.gradle.kts index b4cfebdb..8027dfdb 100644 --- a/kamel-core/build.gradle.kts +++ b/kamel-core/build.gradle.kts @@ -115,3 +115,10 @@ kotlin { } } + +// https://youtrack.jetbrains.com/issue/KT-46466 +val dependsOnTasks = mutableListOf() +tasks.withType().configureEach { + dependsOnTasks.add(this.name.replace("publish", "sign").replaceAfter("Publication", "")) + dependsOn(dependsOnTasks) +} \ No newline at end of file diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index a11c2d3e..5da9acf2 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -157,3 +157,10 @@ kotlin { } } + +// https://youtrack.jetbrains.com/issue/KT-46466 +val dependsOnTasks = mutableListOf() +tasks.withType().configureEach { + dependsOnTasks.add(this.name.replace("publish", "sign").replaceAfter("Publication", "")) + dependsOn(dependsOnTasks) +} \ No newline at end of file diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index aad19d39..10befde4 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -2,6 +2,27 @@ # yarn lockfile v1 +"@babel/code-frame@^7.10.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39" + integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/helper-validator-identifier@^7.18.6": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -93,6 +114,48 @@ dependencies: make-plural "^7.0.0" +"@rollup/plugin-commonjs@^21.0.1": + version "21.1.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-21.1.0.tgz#45576d7b47609af2db87f55a6d4b46e44fc3a553" + integrity sha512-6ZtHx3VHIp2ReNNDxHjuUml6ur+WcQ28N1yHgCQwsbNkQg2suhxGMDQGJOn/KuDxKtd1xuZP5xSTwBA4GQ8hbA== + dependencies: + "@rollup/pluginutils" "^3.1.0" + commondir "^1.0.1" + estree-walker "^2.0.1" + glob "^7.1.6" + is-reference "^1.2.1" + magic-string "^0.25.7" + resolve "^1.17.0" + +"@rollup/plugin-node-resolve@^13.1.3": + version "13.3.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz#da1c5c5ce8316cef96a2f823d111c1e4e498801c" + integrity sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw== + dependencies: + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" + deepmerge "^4.2.2" + is-builtin-module "^3.1.0" + is-module "^1.0.0" + resolve "^1.19.0" + +"@rollup/plugin-typescript@^8.3.0": + version "8.5.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-8.5.0.tgz#7ea11599a15b0a30fa7ea69ce3b791d41b862515" + integrity sha512-wMv1/scv0m/rXx21wD2IsBbJFba8wGF3ErJIr6IKRfRj49S85Lszbxb4DCo8iILpluTjk2GAAu9CoZt4G3ppgQ== + dependencies: + "@rollup/pluginutils" "^3.1.0" + resolve "^1.17.0" + +"@rollup/pluginutils@^3.0.9", "@rollup/pluginutils@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + picomatch "^2.2.2" + "@socket.io/component-emitter@~3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" @@ -159,6 +222,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + "@types/estree@^0.0.51": version "0.0.51" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" @@ -205,6 +273,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.17.tgz#52438111ea98f77475470fc62d79b9eb96bb2c92" integrity sha512-0UyfUnt02zIuqp7yC8RYtDkp/vo8bFaQ13KkSEvUAohPOAlnVNbj5Fi3fgPSuwzakS+EvvnnZ4x9y7i6ASaSPQ== +"@types/node@^12.12.14": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + "@types/qs@*": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" @@ -215,6 +288,13 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== +"@types/resolve@1.17.1": + version "1.17.1" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" + integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== + dependencies: + "@types/node" "*" + "@types/retry@0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" @@ -427,11 +507,16 @@ acorn-import-assertions@^1.7.6: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== -acorn@^8.4.1, acorn@^8.5.0: +acorn@^8.5.0: version "8.8.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== +acorn@^8.7.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + ajv-formats@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -486,6 +571,13 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -516,6 +608,11 @@ array-flatten@^2.1.2: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -540,11 +637,6 @@ bcp-47@1.0.8: is-alphanumerical "^1.0.0" is-decimal "^1.0.0" -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -620,6 +712,11 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +builtin-modules@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -648,6 +745,15 @@ caniuse-lite@^1.0.30001370: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001397.tgz#010d9d56e3b8abcd8df261d0a94b22426271a15f" integrity sha512-SW9N2TbCdLf0eiNDRrrQXx2sOkaakNZbCjgNpPyMJJbiOrU5QzMIrXOVMRM1myBXTD5iTkdrtU/EguCrBocHlA== +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -694,6 +800,13 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -701,6 +814,11 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" @@ -721,6 +839,11 @@ commander@^7.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + compressible@~2.0.16: version "2.0.18" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" @@ -746,10 +869,10 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== +connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== connect@^3.7.0: version "3.7.0" @@ -810,6 +933,25 @@ cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +css-loader@6.7.3: + version "6.7.3" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.3.tgz#1e8799f3ccc5874fdd55461af51137fcc5befbcd" + integrity sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.19" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.3.8" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + custom-event@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" @@ -839,6 +981,16 @@ decamelize@^4.0.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== +decode-uri-component@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + default-gateway@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" @@ -926,11 +1078,6 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -957,10 +1104,10 @@ engine.io@~6.2.0: engine.io-parser "~5.0.3" ws "~8.2.3" -enhanced-resolve@^5.9.3: - version "5.10.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" - integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== +enhanced-resolve@^5.10.0: + version "5.13.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.13.0.tgz#26d1ecc448c02de997133217b5c1053f34a0a275" + integrity sha512-eyV8f0y1+bzyfh8xAwW/WTSZpLbjhqc4ne9eGSH4Zo2ejdyiNG9pU6mf9DG8a7+Auk6MFTlNOT4Y2y/9k8GKVg== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -995,6 +1142,11 @@ escape-string-regexp@4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + eslint-scope@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -1020,6 +1172,16 @@ estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== + +estree-walker@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" @@ -1119,14 +1281,6 @@ faye-websocket@^0.11.3: dependencies: websocket-driver ">=0.5.1" -file-loader@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" - integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -1191,7 +1345,7 @@ follow-redirects@^1.0.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== -format-util@1.0.5: +format-util@1.0.5, format-util@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.5.tgz#1ffb450c8a03e7bccffe40643180918cc297d271" integrity sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg== @@ -1278,7 +1432,7 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3, glob@^7.1.7: +glob@^7.1.3, glob@^7.1.6, glob@^7.1.7: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -1305,6 +1459,11 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -1412,6 +1571,11 @@ iconv-lite@^0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + import-local@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" @@ -1473,6 +1637,20 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-builtin-module@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" + integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== + dependencies: + builtin-modules "^3.3.0" + +is-core-module@^2.11.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4" + integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== + dependencies: + has "^1.0.3" + is-core-module@^2.9.0: version "2.10.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" @@ -1507,6 +1685,11 @@ is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -1529,6 +1712,13 @@ is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-reference@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== + dependencies: + "@types/estree" "*" + is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" @@ -1566,6 +1756,15 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +jest-worker@^26.2.1: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^7.0.0" + jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" @@ -1575,6 +1774,11 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + js-yaml@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -1597,11 +1801,6 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json5@^2.1.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== - jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -1679,15 +1878,6 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== -loader-utils@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" - integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -1726,6 +1916,20 @@ log4js@^6.4.1: rfdc "^1.3.0" streamroller "^3.1.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +magic-string@^0.25.7: + version "0.25.9" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" + integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== + dependencies: + sourcemap-codec "^1.4.8" + make-plural@^6.2.1: version "6.2.2" resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-6.2.2.tgz#beb5fd751355e72660eeb2218bb98eec92853c6c" @@ -1798,6 +2002,13 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mini-css-extract-plugin@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz#9a1251d15f2035c342d99a468ab9da7a0451b71e" + integrity sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg== + dependencies: + schema-utils "^4.0.0" + minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -1890,6 +2101,11 @@ nanoid@3.3.3: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== +nanoid@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== + negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -2062,7 +2278,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -2074,6 +2290,56 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" + integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== + +postcss-modules-local-by-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" + integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" + integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: + version "6.0.12" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.12.tgz#2efae5ffab3c8bfb2b7fbf0c426e3bca616c4abb" + integrity sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.4.19: + version "8.4.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.23.tgz#df0aee9ac7c5e53e1075c24a3613496f9e6552ab" + integrity sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -2189,6 +2455,15 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve@^1.17.0, resolve@^1.19.0: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^1.9.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" @@ -2215,6 +2490,31 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +rollup-plugin-sourcemaps@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.6.3.tgz#bf93913ffe056e414419607f1d02780d7ece84ed" + integrity sha512-paFu+nT1xvuO1tPFYXGe+XnQvg4Hjqv/eIhG8i5EspfYYPBKL57X7iVbfv55aNVASg3dzWvES9dmWsL2KhfByw== + dependencies: + "@rollup/pluginutils" "^3.0.9" + source-map-resolve "^0.6.0" + +rollup-plugin-terser@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" + integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ== + dependencies: + "@babel/code-frame" "^7.10.4" + jest-worker "^26.2.1" + serialize-javascript "^4.0.0" + terser "^5.0.0" + +rollup@^2.68.0: + version "2.79.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" + integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== + optionalDependencies: + fsevents "~2.3.2" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -2235,7 +2535,7 @@ safe-identifier@^0.4.1: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: +schema-utils@^3.1.0, schema-utils@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== @@ -2266,6 +2566,13 @@ selfsigned@^2.0.1: dependencies: node-forge "^1" +semver@^7.3.8: + version "7.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.0.tgz#ed8c5dc8efb6c629c88b23d41dc9bf40c1d96cd0" + integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA== + dependencies: + lru-cache "^6.0.0" + send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -2292,6 +2599,13 @@ serialize-javascript@6.0.0, serialize-javascript@^6.0.0: dependencies: randombytes "^2.1.0" +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" + serve-index@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" @@ -2406,6 +2720,14 @@ source-map-loader@4.0.0: iconv-lite "^0.6.3" source-map-js "^1.0.2" +source-map-resolve@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" + integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -2419,6 +2741,11 @@ source-map@^0.6.0, source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +sourcemap-codec@^1.4.8: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + spdy-transport@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" @@ -2501,6 +2828,11 @@ strip-json-comments@3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +style-loader@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" + integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== + supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -2508,7 +2840,14 @@ supports-color@8.1.1, supports-color@^8.0.0: dependencies: has-flag "^4.0.0" -supports-color@^7.1.0: +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== @@ -2536,6 +2875,16 @@ terser-webpack-plugin@^5.1.3: serialize-javascript "^6.0.0" terser "^5.14.1" +terser@^5.0.0: + version "5.17.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.17.1.tgz#948f10830454761e2eeedc6debe45c532c83fd69" + integrity sha512-hVl35zClmpisy6oaoKALOpS0rDYLxRFLHhRuDlEGTKey9qHjS1w9GMORjuwIMt70Wan4lwsLYyWDVnWgF+KUEw== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + terser@^5.14.1: version "5.15.0" resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.0.tgz#e16967894eeba6e1091509ec83f0c60e179f2425" @@ -2575,6 +2924,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +tslib@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" + integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -2588,6 +2942,16 @@ typescript@3.9.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== +typescript@4.7.4: + version "4.7.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" + integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== + +typescript@^3.7.2: + version "3.9.10" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" + integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== + ua-parser-js@^0.7.30: version "0.7.31" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6" @@ -2618,16 +2982,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-loader@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" - integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== - dependencies: - loader-utils "^2.0.0" - mime-types "^2.1.27" - schema-utils "^3.0.0" - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -2652,7 +3007,7 @@ void-elements@^2.0.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== -watchpack@^2.3.1: +watchpack@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== @@ -2701,10 +3056,10 @@ webpack-dev-middleware@^5.3.1: range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@4.9.2: - version "4.9.2" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.9.2.tgz#c188db28c7bff12f87deda2a5595679ebbc3c9bc" - integrity sha512-H95Ns95dP24ZsEzO6G9iT+PNw4Q7ltll1GfJHV4fKphuHWgKFzGHWi4alTlTnpk1SPPk41X+l2RB7rLfIhnB9Q== +webpack-dev-server@4.9.3: + version "4.9.3" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz#2360a5d6d532acb5410a668417ad549ee3b8a3c9" + integrity sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -2718,7 +3073,7 @@ webpack-dev-server@4.9.2: chokidar "^3.5.3" colorette "^2.0.10" compression "^1.7.4" - connect-history-api-fallback "^1.6.0" + connect-history-api-fallback "^2.0.0" default-gateway "^6.0.3" express "^4.17.3" graceful-fs "^4.2.6" @@ -2756,21 +3111,21 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@5.73.0: - version "5.73.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.73.0.tgz#bbd17738f8a53ee5760ea2f59dce7f3431d35d38" - integrity sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA== +webpack@5.74.0: + version "5.74.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980" + integrity sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51" "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.4.1" + acorn "^8.7.1" acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.9.3" + enhanced-resolve "^5.10.0" es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" @@ -2783,7 +3138,7 @@ webpack@5.73.0: schema-utils "^3.1.0" tapable "^2.1.1" terser-webpack-plugin "^5.1.3" - watchpack "^2.3.1" + watchpack "^2.4.0" webpack-sources "^3.2.3" websocket-driver@>=0.5.1, websocket-driver@^0.7.4: @@ -2866,6 +3221,11 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" From 9f9191751eeb9a6283e7837e7f9e2be2f64bf85f Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sat, 6 May 2023 03:04:52 -0400 Subject: [PATCH 33/74] implement SvgDecoder for nonjvm --- .../src/nonJvmMain/kotlin/DrawCache.kt | 88 ++++++++++++++ .../io/kamel/image/decoder/SvgDecoder.kt | 12 +- .../src/nonJvmMain/kotlin/loadSvgPainter.kt | 110 ++++++++++++++++++ .../io/kamel/samples/darwinFileSample.kt | 10 +- 4 files changed, 208 insertions(+), 12 deletions(-) create mode 100644 kamel-image/src/nonJvmMain/kotlin/DrawCache.kt create mode 100644 kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt diff --git a/kamel-image/src/nonJvmMain/kotlin/DrawCache.kt b/kamel-image/src/nonJvmMain/kotlin/DrawCache.kt new file mode 100644 index 00000000..ab7bf600 --- /dev/null +++ b/kamel-image/src/nonJvmMain/kotlin/DrawCache.kt @@ -0,0 +1,88 @@ +import androidx.compose.ui.graphics.BlendMode +import androidx.compose.ui.graphics.Canvas +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.drawscope.CanvasDrawScope +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.toSize + +/** + * Creates a drawing environment that directs its drawing commands to an [ImageBitmap] + * which can be drawn directly in another [DrawScope] instance. This is useful to cache + * complicated drawing commands across frames especially if the content has not changed. + * Additionally some drawing operations such as rendering paths are done purely in + * software so it is beneficial to cache the result and render the contents + * directly through a texture as done by [DrawScope.drawImage] + */ +internal class DrawCache { + + @PublishedApi internal var mCachedImage: ImageBitmap? = null + private var cachedCanvas: Canvas? = null + private var scopeDensity: Density? = null + private var layoutDirection: LayoutDirection = LayoutDirection.Ltr + private var size: IntSize = IntSize.Zero + + private val cacheScope = CanvasDrawScope() + + /** + * Draw the contents of the lambda with receiver scope into an [ImageBitmap] with the provided + * size. If the same size is provided across calls, the same [ImageBitmap] instance is + * re-used and the contents are cleared out before drawing content in it again + */ + fun drawCachedImage( + size: IntSize, + density: Density, + layoutDirection: LayoutDirection, + block: DrawScope.() -> Unit + ) { + this.scopeDensity = density + this.layoutDirection = layoutDirection + var targetImage = mCachedImage + var targetCanvas = cachedCanvas + if (targetImage == null || + targetCanvas == null || + size.width > targetImage.width || + size.height > targetImage.height + ) { + targetImage = ImageBitmap(size.width, size.height) + targetCanvas = Canvas(targetImage) + + mCachedImage = targetImage + cachedCanvas = targetCanvas + } + this.size = size + cacheScope.draw(density, layoutDirection, targetCanvas, size.toSize()) { + clear() + block() + } + targetImage.prepareToDraw() + } + + /** + * Draw the cached content into the provided [DrawScope] instance + */ + fun drawInto( + target: DrawScope, + alpha: Float = 1.0f, + colorFilter: ColorFilter? = null + ) { + val targetImage = mCachedImage + check(targetImage != null) { + "drawCachedImage must be invoked first before attempting to draw the result " + + "into another destination" + } + target.drawImage(targetImage, srcSize = size, alpha = alpha, colorFilter = colorFilter) + } + + /** + * Helper method to clear contents of the draw environment from the given bounds of the + * DrawScope + */ + private fun DrawScope.clear() { + drawRect(color = Color.Black, blendMode = BlendMode.Clear) + } +} \ No newline at end of file diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt index 4b9d854d..737afcfb 100644 --- a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/SvgDecoder.kt @@ -1,22 +1,22 @@ package io.kamel.image.decoder import androidx.compose.ui.graphics.painter.Painter -//import androidx.compose.ui.res.loadSvgPainter +import androidx.compose.ui.res.loadSvgPainter import io.kamel.core.config.ResourceConfig import io.kamel.core.decoder.Decoder +import io.ktor.util.* import io.ktor.utils.io.* import kotlin.reflect.KClass -//import io.ktor.utils.io.jvm.javaio.* internal object SvgDecoder : Decoder { override val outputKClass: KClass = Painter::class override suspend fun decode(channel: ByteReadChannel, resourceConfig: ResourceConfig): Painter { - return TODO()/*loadSvgPainter( - channel.toInputStream(), + return loadSvgPainter( + channel.toByteArray(), resourceConfig.density - )*/ + ) } -} \ No newline at end of file +} diff --git a/kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt b/kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt new file mode 100644 index 00000000..c7060df9 --- /dev/null +++ b/kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt @@ -0,0 +1,110 @@ +package androidx.compose.ui.res + +import DrawCache +import androidx.compose.runtime.Composable +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.geometry.isSpecified +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.drawscope.drawIntoCanvas +import androidx.compose.ui.graphics.nativeCanvas +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.IntSize +import io.ktor.util.* +import io.ktor.utils.io.* +import org.jetbrains.skia.Data +import org.jetbrains.skia.Rect +import org.jetbrains.skia.svg.* +import kotlin.math.ceil + +/** + * Synchronously load an SVG image from some [inputStream]. + * + * In contrast to [svgResource] this function isn't [Composable] + * + * @param inputStream input stream to load an SVG resource. All bytes will be read from this stream, + * but stream will not be closed after this method. + * @param density density that will be used to set the intrinsic size of the Painter. If the image + * will be drawn with the specified size, density will have no effect. + * @return the decoded SVG image associated with the resource + */ +fun loadSvgPainter( + bytes: ByteArray, + density: Density +): Painter { + val data = Data.makeFromBytes(bytes) + return SVGPainter(SVGDOM(data), density) +} + +private class SVGPainter( + private val dom: SVGDOM, + private val density: Density +) : Painter() { + private val root = dom.root + + private val defaultSizePx: Size = run { + val width = root?.width?.withUnit(SVGLengthUnit.PX)?.value ?: 0f + val height = root?.height?.withUnit(SVGLengthUnit.PX)?.value ?: 0f + if (width == 0f && height == 0f) { + Size.Unspecified + } else { + Size(width, height) + } + } + + init { + if (root?.viewBox == null && defaultSizePx.isSpecified) { + root?.viewBox = Rect.makeXYWH(0f, 0f, defaultSizePx.width, defaultSizePx.height) + } + } + + override val intrinsicSize: Size + get() { + return if (defaultSizePx.isSpecified) { + defaultSizePx * density.density + } else { + Size.Unspecified + } + } + + private var previousDrawSize: Size = Size.Unspecified + private var alpha: Float = 1.0f + private var colorFilter: ColorFilter? = null + + // with caching into bitmap FPS is 3x-4x higher (tested with idea-logo.svg with 30x30 icons) + private val drawCache = DrawCache() + + override fun applyAlpha(alpha: Float): Boolean { + this.alpha = alpha + return true + } + + override fun applyColorFilter(colorFilter: ColorFilter?): Boolean { + this.colorFilter = colorFilter + return true + } + + override fun DrawScope.onDraw() { + if (previousDrawSize != size) { + drawCache.drawCachedImage( + IntSize(ceil(size.width).toInt(), ceil(size.height).toInt()), + density = this, + layoutDirection, + ) { + drawSvg(size) + } + } + + drawCache.drawInto(this, alpha, colorFilter) + } + + private fun DrawScope.drawSvg(size: Size) { + drawIntoCanvas { canvas -> + root?.width = SVGLength(size.width, SVGLengthUnit.PX) + root?.height = SVGLength(size.height, SVGLengthUnit.PX) + root?.preserveAspectRatio = SVGPreserveAspectRatio(SVGPreserveAspectRatioAlign.NONE) + dom.render(canvas.nativeCanvas) + } + } +} \ No newline at end of file diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt index 94078f48..866a1c67 100644 --- a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt @@ -9,10 +9,7 @@ import io.kamel.core.config.KamelConfig import io.kamel.core.config.takeFrom import io.kamel.core.utils.File import io.kamel.image.KamelImage -import io.kamel.image.config.Default -import io.kamel.image.config.LocalKamelConfig -import io.kamel.image.config.imageVectorDecoder -import io.kamel.image.config.resourcesFetcher +import io.kamel.image.config.* import io.kamel.image.lazyPainterResource @OptIn(ExperimentalKamelApi::class) @@ -22,16 +19,17 @@ internal fun FileSample() { takeFrom(KamelConfig.Default) resourcesFetcher() imageVectorDecoder() + svgDecoder() } CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { Column { - val file = File(io.kamel.tests.MR.files.Compose.path) + val file = File(io.kamel.tests.MR.files.Kotlin.path) val painterResource = lazyPainterResource(file) KamelImage( painterResource, - contentDescription = "Compose", + contentDescription = "Kotlin", modifier = Modifier.fillMaxSize(), onFailure = { throw it } ) From c7ed46d779ead2776495f10e3a2849dca38391d2 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sat, 6 May 2023 17:23:02 -0400 Subject: [PATCH 34/74] create supervisor job and use now available Dispatchers.IO on native rename Dispatchers.IO to Dispatchers.kamel to avoid confusion note: Using 'plus(Job): Job' is an error. Operator '+' on two Job objects is meaningless. Job is a coroutine context element and `+` is a set-sum operator for coroutine contexts. The job to the right of `+` just replaces the job the left of `+`. --- kamel-core/build.gradle.kts | 1 + .../kotlin/io/kamel/core/config/ResourceConfigBuilder.kt | 7 +++---- .../src/commonMain/kotlin/io/kamel/core/utils/Platform.kt | 5 ++++- .../src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt | 3 ++- .../src/jsMain/kotlin/io/kamel/core/utils/Platform.kt | 2 +- .../src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt | 2 +- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/kamel-core/build.gradle.kts b/kamel-core/build.gradle.kts index 8027dfdb..6fd06d97 100644 --- a/kamel-core/build.gradle.kts +++ b/kamel-core/build.gradle.kts @@ -55,6 +55,7 @@ kotlin { implementation(compose.ui) implementation(compose.foundation) implementation(compose.runtime) + implementation(Dependencies.Coroutines.Core) api(Dependencies.Ktor.Core) } } diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/config/ResourceConfigBuilder.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/config/ResourceConfigBuilder.kt index 112e21f7..71c25f7a 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/config/ResourceConfigBuilder.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/config/ResourceConfigBuilder.kt @@ -1,11 +1,10 @@ package io.kamel.core.config -import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.unit.Density -import io.kamel.core.utils.IO +import io.kamel.core.utils.kamel +import io.kamel.core.utils.supervisorJob import io.ktor.client.request.* import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job import kotlin.coroutines.CoroutineContext public class ResourceConfigBuilder { @@ -20,7 +19,7 @@ public class ResourceConfigBuilder { * CoroutineContext used while loading the resource. * @see ResourceConfig.coroutineContext */ - public var coroutineContext: CoroutineContext = Job() + Dispatchers.IO + public var coroutineContext: CoroutineContext = supervisorJob.plus(Dispatchers.kamel) /** * Screen density. diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/Platform.kt index cc274657..8f9a62a3 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/Platform.kt @@ -2,8 +2,11 @@ package io.kamel.core.utils import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob -internal expect val Dispatchers.IO: CoroutineDispatcher +internal val supervisorJob = SupervisorJob() + +internal expect val Dispatchers.kamel: CoroutineDispatcher public expect class File diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt index 7c270864..f24958f9 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt @@ -4,6 +4,7 @@ import kotlinx.cinterop.addressOf import kotlinx.cinterop.usePinned import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO import platform.Foundation.NSData import platform.Foundation.NSFileHandle import platform.Foundation.NSURL @@ -11,7 +12,7 @@ import platform.Foundation.fileHandleForReadingAtPath import platform.posix.memcpy -internal actual val Dispatchers.IO: CoroutineDispatcher get() = Dispatchers.Default +internal actual val Dispatchers.kamel: CoroutineDispatcher get() = IO public actual class File(public val path: String) { diff --git a/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt index d048851c..d2955d7a 100644 --- a/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers -internal actual val Dispatchers.IO: CoroutineDispatcher get() = Default +internal actual val Dispatchers.kamel: CoroutineDispatcher get() = Default internal actual typealias File = org.w3c.files.File diff --git a/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt b/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt index 583fec62..18ff9fcf 100644 --- a/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt +++ b/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt @@ -5,7 +5,7 @@ import kotlinx.coroutines.Dispatchers import java.net.URI import java.net.URL -internal actual val Dispatchers.IO: CoroutineDispatcher get() = IO +internal actual val Dispatchers.kamel: CoroutineDispatcher get() = IO internal actual typealias File = java.io.File From f97d9c87e55f6ca49f80d592e0e0595dd963fdb5 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sat, 6 May 2023 18:30:30 -0400 Subject: [PATCH 35/74] fix native tests --- kamel-core/build.gradle.kts | 50 +++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/kamel-core/build.gradle.kts b/kamel-core/build.gradle.kts index 6fd06d97..99a65c30 100644 --- a/kamel-core/build.gradle.kts +++ b/kamel-core/build.gradle.kts @@ -1,6 +1,11 @@ -import org.jetbrains.compose.compose import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode +import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractExecutable import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBinary +import org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable +import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink +import org.jetbrains.kotlin.library.impl.KotlinLibraryLayoutImpl +import java.io.FileFilter plugins { multiplatform @@ -122,4 +127,45 @@ val dependsOnTasks = mutableListOf() tasks.withType().configureEach { dependsOnTasks.add(this.name.replace("publish", "sign").replaceAfter("Publication", "")) dependsOn(dependsOnTasks) -} \ No newline at end of file +} + + +// todo: Remove when resolved: https://github.com/icerockdev/moko-resources/issues/372 +tasks.withType() + .matching { linkTask -> + linkTask.binary is AbstractExecutable + } + .configureEach { + val task: KotlinNativeLink = this + + this.doLast { + val binary: NativeBinary = task.binary + val outputDir: File = task.outputFile.get().parentFile + task.libraries + .filter { library -> library.extension == "klib" } + .filter(File::exists) + .forEach { inputFile -> + val klibKonan = org.jetbrains.kotlin.konan.file.File(inputFile.path) + val klib = KotlinLibraryLayoutImpl( + klib = klibKonan, + component = "default" + ) + val layout = klib.extractingToTemp + + // extracting bundles + layout + .resourcesDir + .absolutePath + .let(::File) + .listFiles(FileFilter { it.extension == "bundle" }) + // copying bundles to app + ?.forEach { bundleFile -> + logger.info("${bundleFile.absolutePath} copying to $outputDir") + bundleFile.copyRecursively( + target = File(outputDir, bundleFile.name), + overwrite = true + ) + } + } + } + } From bfafcd0c17630e5cab63e9105d51aba4ada5a73b Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sat, 6 May 2023 19:58:30 -0400 Subject: [PATCH 36/74] fix js test --- kamel-core/src/jsMain/kotlin/io/kamel/core/mapper/Mappers.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kamel-core/src/jsMain/kotlin/io/kamel/core/mapper/Mappers.kt b/kamel-core/src/jsMain/kotlin/io/kamel/core/mapper/Mappers.kt index 24780962..00bba534 100644 --- a/kamel-core/src/jsMain/kotlin/io/kamel/core/mapper/Mappers.kt +++ b/kamel-core/src/jsMain/kotlin/io/kamel/core/mapper/Mappers.kt @@ -11,7 +11,7 @@ internal actual val URLMapper: Mapper = object : Mapper { override val outputKClass: KClass get() = Url::class - override fun map(input: URL): Url = StringMapper.map(input.toString()) + override fun map(input: URL): Url = StringMapper.map(input.toString().removeSuffix("/")) } From df3bec0929d8c17b36d69f6fcf9e885e95a63773 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sat, 6 May 2023 20:03:21 -0400 Subject: [PATCH 37/74] add todo notes --- kamel-image/src/nonJvmMain/kotlin/DrawCache.kt | 3 +++ kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/kamel-image/src/nonJvmMain/kotlin/DrawCache.kt b/kamel-image/src/nonJvmMain/kotlin/DrawCache.kt index ab7bf600..58c83b0e 100644 --- a/kamel-image/src/nonJvmMain/kotlin/DrawCache.kt +++ b/kamel-image/src/nonJvmMain/kotlin/DrawCache.kt @@ -18,6 +18,9 @@ import androidx.compose.ui.unit.toSize * software so it is beneficial to cache the result and render the contents * directly through a texture as done by [DrawScope.drawImage] */ +// Note copied from here: +// https://github.com/JetBrains/compose-multiplatform-core/blob/5c26b7b9f5619ee4f319c6caf43192851b8ee15e/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/graphics/vector/DrawCache.kt#L39 +// todo: remove when available in common androidx internal class DrawCache { @PublishedApi internal var mCachedImage: ImageBitmap? = null diff --git a/kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt b/kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt index c7060df9..fc8cbe52 100644 --- a/kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt +++ b/kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt @@ -29,6 +29,9 @@ import kotlin.math.ceil * will be drawn with the specified size, density will have no effect. * @return the decoded SVG image associated with the resource */ +// Note: copied from here: +// https://github.com/JetBrains/compose-multiplatform-core/blob/5c26b7b9f5619ee4f319c6caf43192851b8ee15e/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/res/DesktopSvgResources.desktop.kt#L51 +// todo: remove when available in common androidx fun loadSvgPainter( bytes: ByteArray, density: Density From 30746e67c479c4e7a6f11f7a8ee2a4aa984d9847 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sat, 6 May 2023 23:39:00 -0400 Subject: [PATCH 38/74] implement loadXmlImageVector for nonJvm --- kamel-image/build.gradle.kts | 3 + .../src/nonJvmMain/kotlin/ValueParsers.kt | 105 +++++++ .../src/nonJvmMain/kotlin/XmlVectorParser.kt | 265 ++++++++++++++++++ .../kamel/image/decoder/ImageVectorDecoder.kt | 10 +- .../nonJvmMain/kotlin/loadXmlImageVector.kt | 27 ++ .../io/kamel/samples/ImageVectorSample.kt | 39 +++ .../kotlin/io/kamel/samples/launcher.kt | 6 + .../{Compose.xml => MR/files/ComposeXml.xml} | 0 8 files changed, 449 insertions(+), 6 deletions(-) create mode 100644 kamel-image/src/nonJvmMain/kotlin/ValueParsers.kt create mode 100644 kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt create mode 100644 kamel-image/src/nonJvmMain/kotlin/loadXmlImageVector.kt create mode 100644 kamel-samples/src/darwinMain/kotlin/io/kamel/samples/ImageVectorSample.kt rename kamel-tests/src/commonMain/resources/{Compose.xml => MR/files/ComposeXml.xml} (100%) diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 5da9acf2..803e6385 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -116,6 +116,9 @@ kotlin { val nonJvmMain by creating { dependsOn(commonMain) + dependencies{ + implementation("io.github.pdvrieze.xmlutil:serialization:0.86.0") + } } val nonJvmTest by creating { diff --git a/kamel-image/src/nonJvmMain/kotlin/ValueParsers.kt b/kamel-image/src/nonJvmMain/kotlin/ValueParsers.kt new file mode 100644 index 00000000..4f259529 --- /dev/null +++ b/kamel-image/src/nonJvmMain/kotlin/ValueParsers.kt @@ -0,0 +1,105 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import androidx.compose.ui.graphics.PathFillType +import androidx.compose.ui.graphics.StrokeCap +import androidx.compose.ui.graphics.StrokeJoin +import androidx.compose.ui.graphics.TileMode +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +// copied from +// https://github.com/JetBrains/compose-multiplatform-core/blob/5c26b7b9f5619ee4f319c6caf43192851b8ee15e/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/res/vector/DesktopValueParsers.desktop.kt#L29 + +private const val ALPHA_MASK = 0xFF000000.toInt() + +// parseColorValue is copied from Android: +// https://cs.android.com/android-studio/platform/tools/base/+/05fadd8cb2aaafb77da02048c7a240b2147ff293:sdk-common/src/main/java/com/android/ide/common/vectordrawable/VdUtil.kt;l=58 +/** + * Parses a color value in #AARRGGBB format. + * + * @param color the color value string + * @return the integer color value + */ +internal fun parseColorValue(color: String): Int { + require(color.startsWith("#")) { "Invalid color value $color" } + + return when (color.length) { + 7 -> { + // #RRGGBB + color.substring(1).toUInt( 16).toInt() or ALPHA_MASK + } + 9 -> { + // #AARRGGBB + color.substring(1).toUInt( 16).toInt() + } + 4 -> { + // #RGB + val v = color.substring(1).toUInt( 16).toInt() + var k = (v shr 8 and 0xF) * 0x110000 + k = k or (v shr 4 and 0xF) * 0x1100 + k = k or (v and 0xF) * 0x11 + k or ALPHA_MASK + } + 5 -> { + // #ARGB + val v = color.substring(1).toUInt( 16).toInt() + var k = (v shr 12 and 0xF) * 0x11000000 + k = k or (v shr 8 and 0xF) * 0x110000 + k = k or (v shr 4 and 0xF) * 0x1100 + k = k or (v and 0xF) * 0x11 + k or ALPHA_MASK + } + else -> ALPHA_MASK + } +} + +internal fun parseFillType(fillType: String): PathFillType = when (fillType) { + "nonZero" -> PathFillType.NonZero + "evenOdd" -> PathFillType.EvenOdd + else -> throw UnsupportedOperationException("unknown fillType: $fillType") +} + +internal fun parseStrokeCap(strokeCap: String): StrokeCap = when (strokeCap) { + "butt" -> StrokeCap.Butt + "round" -> StrokeCap.Round + "square" -> StrokeCap.Square + else -> throw UnsupportedOperationException("unknown strokeCap: $strokeCap") +} + +internal fun parseStrokeJoin(strokeJoin: String): StrokeJoin = when (strokeJoin) { + "miter" -> StrokeJoin.Miter + "round" -> StrokeJoin.Round + "bevel" -> StrokeJoin.Bevel + else -> throw UnsupportedOperationException("unknown strokeJoin: $strokeJoin") +} + +internal fun parseTileMode(tileMode: String): TileMode = when (tileMode) { + "clamp" -> TileMode.Clamp + "repeated" -> TileMode.Repeated + "mirror" -> TileMode.Mirror + else -> throw throw UnsupportedOperationException("unknown tileMode: $tileMode") +} + +internal fun String?.parseDp(density: Density): Dp = with(density) { + return when { + this@parseDp == null -> 0f.dp + endsWith("dp") -> removeSuffix("dp").toFloat().dp + endsWith("px") -> removeSuffix("px").toFloat().toDp() + else -> throw UnsupportedOperationException("value should ends with dp or px") + } +} \ No newline at end of file diff --git a/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt b/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt new file mode 100644 index 00000000..9ed7ec94 --- /dev/null +++ b/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt @@ -0,0 +1,265 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.* +import androidx.compose.ui.graphics.vector.* +import androidx.compose.ui.unit.Density +import nl.adaptivity.xmlutil.dom.* + +// Parsing logic is the same as in Android implementation +// (compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/graphics/vector/compat/XmlVectorParser.kt) +// +// Except there is no support for linking with external resources +// (for example, we can't reference to color defined in another file) +// +// Specification: +// https://developer.android.com/reference/android/graphics/drawable/VectorDrawable + +// ported from +// https://github.com/JetBrains/compose-multiplatform-core/blob/5c26b7b9f5619ee4f319c6caf43192851b8ee15e/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/res/vector/DesktopXmlVectorParser.desktop.kt#L72 +// to use https://github.com/pdvrieze/xmlutil + +private const val ANDROID_NS = "http://schemas.android.com/apk/res/android" +private const val AAPT_NS = "http://schemas.android.com/aapt" + +private class BuildContext { + val currentGroups = mutableListOf() + + enum class Group { + /** + * Group that exists in xml file + */ + Real, + + /** + * Group that doesn't exist in xml file. We add it manually when we see node. + * It will be automatically popped when the real group will be popped. + */ + Virtual + } +} + +internal fun Element.parseVectorRoot(density: Density): ImageVector { + val context = BuildContext() + val builder = ImageVector.Builder( + defaultWidth = attributeOrNull(ANDROID_NS, "width").parseDp(density), + defaultHeight = attributeOrNull(ANDROID_NS, "height").parseDp(density), + viewportWidth = attributeOrNull(ANDROID_NS, "viewportWidth")?.toFloat() ?: 0f, + viewportHeight = attributeOrNull(ANDROID_NS, "viewportHeight")?.toFloat() ?: 0f + ) + parseVectorNodes(builder, context) + return builder.build() +} + +private fun Element.parseVectorNodes(builder: ImageVector.Builder, context: BuildContext) { + childrenSequence + .filterIsInstance() + .forEach { + it.parseVectorNode(builder, context) + } +} + +private fun Element.parseVectorNode(builder: ImageVector.Builder, context: BuildContext) { + when (nodeName) { + "path" -> parsePath(builder) + "clip-path" -> parseClipPath(builder, context) + "group" -> parseGroup(builder, context) + } +} + +private fun Element.parsePath(builder: ImageVector.Builder) { + builder.addPath( + pathData = addPathNodes(attributeOrNull(ANDROID_NS, "pathData")), + pathFillType = attributeOrNull(ANDROID_NS, "fillType") + ?.let(::parseFillType) ?: PathFillType.NonZero, + name = attributeOrNull(ANDROID_NS, "name") ?: "", + fill = attributeOrNull(ANDROID_NS, "fillColor")?.let(::parseStringBrush) + ?: apptAttr(ANDROID_NS, "fillColor")?.let(Element::parseElementBrush), + fillAlpha = attributeOrNull(ANDROID_NS, "fillAlpha")?.toFloat() ?: 1.0f, + stroke = attributeOrNull(ANDROID_NS, "strokeColor")?.let(::parseStringBrush) + ?: apptAttr(ANDROID_NS, "strokeColor")?.let(Element::parseElementBrush), + strokeAlpha = attributeOrNull(ANDROID_NS, "strokeAlpha")?.toFloat() ?: 1.0f, + strokeLineWidth = attributeOrNull(ANDROID_NS, "strokeWidth")?.toFloat() ?: 1.0f, + strokeLineCap = attributeOrNull(ANDROID_NS, "strokeLineCap") + ?.let(::parseStrokeCap) ?: StrokeCap.Butt, + strokeLineJoin = attributeOrNull(ANDROID_NS, "strokeLineJoin") + ?.let(::parseStrokeJoin) ?: StrokeJoin.Miter, + strokeLineMiter = attributeOrNull(ANDROID_NS, "strokeMiterLimit")?.toFloat() ?: 1.0f, + trimPathStart = attributeOrNull(ANDROID_NS, "trimPathStart")?.toFloat() ?: 0.0f, + trimPathEnd = attributeOrNull(ANDROID_NS, "trimPathEnd")?.toFloat() ?: 1.0f, + trimPathOffset = attributeOrNull(ANDROID_NS, "trimPathOffset")?.toFloat() ?: 0.0f + ) +} + +private fun Element.parseClipPath(builder: ImageVector.Builder, context: BuildContext) { + builder.addGroup( + name = attributeOrNull(ANDROID_NS, "name") ?: "", + clipPathData = addPathNodes(attributeOrNull(ANDROID_NS, "pathData")) + ) + context.currentGroups.add(BuildContext.Group.Virtual) +} + +private fun Element.parseGroup(builder: ImageVector.Builder, context: BuildContext) { + builder.addGroup( + attributeOrNull(ANDROID_NS, "name") ?: "", + attributeOrNull(ANDROID_NS, "rotation")?.toFloat() ?: DefaultRotation, + attributeOrNull(ANDROID_NS, "pivotX")?.toFloat() ?: DefaultPivotX, + attributeOrNull(ANDROID_NS, "pivotY")?.toFloat() ?: DefaultPivotY, + attributeOrNull(ANDROID_NS, "scaleX")?.toFloat() ?: DefaultScaleX, + attributeOrNull(ANDROID_NS, "scaleY")?.toFloat() ?: DefaultScaleY, + attributeOrNull(ANDROID_NS, "translateX")?.toFloat() ?: DefaultTranslationX, + attributeOrNull(ANDROID_NS, "translateY")?.toFloat() ?: DefaultTranslationY, + EmptyPath + ) + context.currentGroups.add(BuildContext.Group.Real) + + parseVectorNodes(builder, context) + + do { + val removedGroup = context.currentGroups.removeLastOrNull() + builder.clearGroup() + } while (removedGroup == BuildContext.Group.Virtual) +} + +private fun parseStringBrush(str: String) = SolidColor(Color(parseColorValue(str))) + +private fun Element.parseElementBrush(): Brush? = + childrenSequence + .filterIsInstance() + .find { it.nodeName == "gradient" } + ?.parseGradient() + +private fun Element.parseGradient(): Brush? { + return when (attributeOrNull(ANDROID_NS, "type")) { + "linear" -> parseLinearGradient() + "radial" -> parseRadialGradient() + "sweep" -> parseSweepGradient() + else -> null + } +} + +@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS") +private fun Element.parseLinearGradient() = Brush.linearGradient( + colorStops = parseColorStops(), + start = Offset( + attributeOrNull(ANDROID_NS, "startX")?.toFloat() ?: 0f, + attributeOrNull(ANDROID_NS, "startY")?.toFloat() ?: 0f + ), + end = Offset( + attributeOrNull(ANDROID_NS, "endX")?.toFloat() ?: 0f, + attributeOrNull(ANDROID_NS, "endY")?.toFloat() ?: 0f + ), + tileMode = attributeOrNull(ANDROID_NS, "tileMode")?.let(::parseTileMode) ?: TileMode.Clamp +) + +@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS") +private fun Element.parseRadialGradient() = Brush.radialGradient( + colorStops = parseColorStops(), + center = Offset( + attributeOrNull(ANDROID_NS, "centerX")?.toFloat() ?: 0f, + attributeOrNull(ANDROID_NS, "centerY")?.toFloat() ?: 0f + ), + radius = attributeOrNull(ANDROID_NS, "gradientRadius")?.toFloat() ?: 0f, + tileMode = attributeOrNull(ANDROID_NS, "tileMode")?.let(::parseTileMode) ?: TileMode.Clamp +) + +@Suppress("CHANGING_ARGUMENTS_EXECUTION_ORDER_FOR_NAMED_VARARGS") +private fun Element.parseSweepGradient() = Brush.sweepGradient( + colorStops = parseColorStops(), + center = Offset( + attributeOrNull(ANDROID_NS, "centerX")?.toFloat() ?: 0f, + attributeOrNull(ANDROID_NS, "centerY")?.toFloat() ?: 0f, + ) +) + +private fun Element.parseColorStops(): Array> { + val items = childrenSequence + .filterIsInstance() + .filter { it.nodeName == "item" } + .toList() + + val colorStops = items.mapIndexedNotNullTo(mutableListOf()) { index, item -> + item.parseColorStop(defaultOffset = index.toFloat() / items.lastIndex.coerceAtLeast(1)) + } + + if (colorStops.isEmpty()) { + val startColor = attributeOrNull(ANDROID_NS, "startColor")?.let(::parseColorValue) + val centerColor = attributeOrNull(ANDROID_NS, "centerColor")?.let(::parseColorValue) + val endColor = attributeOrNull(ANDROID_NS, "endColor")?.let(::parseColorValue) + + if (startColor != null) { + colorStops.add(0f to Color(startColor)) + } + if (centerColor != null) { + colorStops.add(0.5f to Color(centerColor)) + } + if (endColor != null) { + colorStops.add(1f to Color(endColor)) + } + } + + return colorStops.toTypedArray() +} + +private fun Element.parseColorStop(defaultOffset: Float): Pair? { + val offset = attributeOrNull(ANDROID_NS, "offset")?.toFloat() ?: defaultOffset + val color = attributeOrNull(ANDROID_NS, "color")?.let(::parseColorValue) ?: return null + return offset to Color(color) +} + +private fun Element.attributeOrNull(namespace: String, name: String): String? { + // accessing by namespace does not appear to be working with https://github.com/pdvrieze/xmlutil v0.86.0 + // todo: figure out how to handle namespaces + // note: ":" had to be prepended to name to load attributes 🤷‍ + val value = getAttribute(":$name") + return value?.ifBlank { null } +} + +/** + * Attribute of an element can be represented as a separate child: + * + * + * + * + * + * + * + * instead of: + * + * + */ +private fun Element.apptAttr( + namespace: String, + name: String +): Element? { + val prefix = lookupPrefix(namespace) ?: return null + return childrenSequence + .filterIsInstance() + .find { + it.namespaceURI == AAPT_NS && it.localName == "attr" && + it.getAttribute("name") == "$prefix:$name" + } +} + +private val Element.childrenSequence + get() = sequence { + for (childNode in childNodes.iterator()) { + yield(childNode) + } + } \ No newline at end of file diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt index 55e4cd1e..b9d809b3 100644 --- a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/decoder/ImageVectorDecoder.kt @@ -4,19 +4,17 @@ import androidx.compose.ui.graphics.vector.ImageVector //import androidx.compose.ui.res.loadXmlImageVector import io.kamel.core.config.ResourceConfig import io.kamel.core.decoder.Decoder +import io.ktor.util.* import io.ktor.utils.io.* +import loadXmlImageVector import kotlin.reflect.KClass -//import io.ktor.utils.io.jvm.javaio.* -//import org.xml.sax.InputSource - internal object ImageVectorDecoder : Decoder { override val outputKClass: KClass = ImageVector::class override suspend fun decode(channel: ByteReadChannel, resourceConfig: ResourceConfig): ImageVector { - TODO() -// val inputSource = InputSource(channel.toInputStream()) -// return loadXmlImageVector(inputSource, resourceConfig.density) + val xml = channel.toByteArray().decodeToString() + return loadXmlImageVector(xml, resourceConfig.density) } } \ No newline at end of file diff --git a/kamel-image/src/nonJvmMain/kotlin/loadXmlImageVector.kt b/kamel-image/src/nonJvmMain/kotlin/loadXmlImageVector.kt new file mode 100644 index 00000000..41a53bd9 --- /dev/null +++ b/kamel-image/src/nonJvmMain/kotlin/loadXmlImageVector.kt @@ -0,0 +1,27 @@ +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.Density +import nl.adaptivity.xmlutil.dom.Element +import nl.adaptivity.xmlutil.serialization.ElementSerializer +import nl.adaptivity.xmlutil.serialization.XML + +/** + * Synchronously load an xml vector image from some [xmlString]. + * + * XML Vector Image came from Android world. See: + * https://developer.android.com/guide/topics/graphics/vector-drawable-resources + * + * On desktop it is fully implemented except there is no resource linking + * (for example, we can't reference to color defined in another file) + * + * @param xmlString input xml vector image string. + * @param density density that will be used to set the default size of the ImageVector. If the image + * will be drawn with the specified size, density will have no effect. + * @return the decoded vector image associated with the image + */ +internal fun loadXmlImageVector( + xmlString: String, + density: Density +): ImageVector { + val element: Element = XML.decodeFromString(ElementSerializer, xmlString) + return element.parseVectorRoot(density) +} \ No newline at end of file diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/ImageVectorSample.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/ImageVectorSample.kt new file mode 100644 index 00000000..fff2fd32 --- /dev/null +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/ImageVectorSample.kt @@ -0,0 +1,39 @@ +package io.kamel.samples + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import io.kamel.core.config.KamelConfig +import io.kamel.core.config.takeFrom +import io.kamel.core.utils.File +import io.kamel.image.KamelImage +import io.kamel.image.config.Default +import io.kamel.image.config.LocalKamelConfig +import io.kamel.image.config.imageVectorDecoder +import io.kamel.image.config.resourcesFetcher +import io.kamel.image.lazyPainterResource +import io.kamel.tests.MR + +@androidx.compose.runtime.Composable +internal fun ImageVectorSample() { + val kamelConfig = KamelConfig { + takeFrom(KamelConfig.Default) + resourcesFetcher() + imageVectorDecoder() + } + + CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { + val file = File(MR.files.ComposeXml.path) + val painterResource = lazyPainterResource(file) + + KamelImage( + painterResource, + contentDescription = "Compose", + modifier = Modifier.fillMaxSize(), + onFailure = { throw it }, + onLoading = { + println(it) + } + ) + } +} \ No newline at end of file diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt index 76600dca..3c926f70 100644 --- a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt @@ -24,10 +24,16 @@ public fun launcher(){ }) { Text("FileSample") } + Button({ + sampleIndex = 2 + }) { + Text("ImageVectorSample") + } } when (sampleIndex) { 0 -> Gallery() 1 -> FileSample() + 2 -> ImageVectorSample() else -> Text("Invalid Sample Index") } } diff --git a/kamel-tests/src/commonMain/resources/Compose.xml b/kamel-tests/src/commonMain/resources/MR/files/ComposeXml.xml similarity index 100% rename from kamel-tests/src/commonMain/resources/Compose.xml rename to kamel-tests/src/commonMain/resources/MR/files/ComposeXml.xml From ab1501f156ecf866ac4b03ab3b0bd0d9c71853d0 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sat, 6 May 2023 23:45:16 -0400 Subject: [PATCH 39/74] refactor comments --- kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt b/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt index 9ed7ec94..94575a8d 100644 --- a/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt +++ b/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt @@ -221,10 +221,13 @@ private fun Element.parseColorStop(defaultOffset: Float): Pair? { return offset to Color(color) } -private fun Element.attributeOrNull(namespace: String, name: String): String? { - // accessing by namespace does not appear to be working with https://github.com/pdvrieze/xmlutil v0.86.0 - // todo: figure out how to handle namespaces - // note: ":" had to be prepended to name to load attributes 🤷‍ +/*** + * Accessing by namespace does not appear to be working with https://github.com/pdvrieze/xmlutil v0.86.0 + * note: ":" had to be prepended to name to load attributes 🤷‍ + * todo: figure out how to handle namespaces + */ +private fun Element.attributeOrNull(@Suppress("UNUSED_PARAMETER") namespace: String, name: String): String? { +// val value = getAttributeNS(namespace,":$name") val value = getAttribute(":$name") return value?.ifBlank { null } } From 3b49d510d567047c439a8f43cf43b4a80e4e4f9e Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sat, 6 May 2023 23:45:35 -0400 Subject: [PATCH 40/74] revert to using LazyVerticalGrid in samples --- .../src/commonMain/kotlin/io/kamel/samples/Gallery.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt index 586dcd2c..8f524d72 100644 --- a/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt +++ b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt @@ -2,8 +2,9 @@ package io.kamel.samples import androidx.compose.foundation.background import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.runtime.* @@ -37,9 +38,7 @@ public fun Gallery() { } Box(Modifier.fillMaxSize()) { - //https://github.com/JetBrains/compose-jb/issues/2061 -// LazyVerticalGrid(columns = GridCells.Fixed(cellsCount), modifier = Modifier.fillMaxSize()) { - LazyColumn(modifier = Modifier.fillMaxSize()) { + LazyVerticalGrid(columns = GridCells.Fixed(cellsCount), modifier = Modifier.fillMaxSize()) { items(items) { imageUrl -> val painterResource: Resource = lazyPainterResource( imageUrl, From d678c74254486f621bbd307ddf04ea7fbf8bab9f Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sat, 6 May 2023 23:47:05 -0400 Subject: [PATCH 41/74] reduce grid padding --- kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt index 8f524d72..5e61ba28 100644 --- a/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt +++ b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/Gallery.kt @@ -50,7 +50,7 @@ public fun Gallery() { contentDescription = null, modifier = Modifier .aspectRatio(1F) - .padding(16.dp) + .padding(8.dp) .shadow(elevation = 8.dp, RoundedCornerShape(16.dp)) .background(Color.White, RoundedCornerShape(16.dp)) .clip(RoundedCornerShape(16.dp)), From 9cc6bdc371fac9bbeedc01b5c760f69727e5bb86 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 00:27:36 -0400 Subject: [PATCH 42/74] fix filtering for elements on js --- kamel-image/src/darwinMain/kotlin/filterIsElement.kt | 5 +++++ kamel-image/src/jsMain/kotlin/filterIsElement.kt | 9 +++++++++ kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt | 8 ++++---- kamel-image/src/nonJvmMain/kotlin/filterIsElement.kt | 4 ++++ .../kotlin/io/kamel/samples/darwinFileSample.kt | 5 ++--- 5 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 kamel-image/src/darwinMain/kotlin/filterIsElement.kt create mode 100644 kamel-image/src/jsMain/kotlin/filterIsElement.kt create mode 100644 kamel-image/src/nonJvmMain/kotlin/filterIsElement.kt diff --git a/kamel-image/src/darwinMain/kotlin/filterIsElement.kt b/kamel-image/src/darwinMain/kotlin/filterIsElement.kt new file mode 100644 index 00000000..c0edaa22 --- /dev/null +++ b/kamel-image/src/darwinMain/kotlin/filterIsElement.kt @@ -0,0 +1,5 @@ +import nl.adaptivity.xmlutil.dom.Element +import nl.adaptivity.xmlutil.dom.Node + +internal actual fun Sequence.filterIsElement(): Sequence = + filterIsInstance() \ No newline at end of file diff --git a/kamel-image/src/jsMain/kotlin/filterIsElement.kt b/kamel-image/src/jsMain/kotlin/filterIsElement.kt new file mode 100644 index 00000000..697ce4d5 --- /dev/null +++ b/kamel-image/src/jsMain/kotlin/filterIsElement.kt @@ -0,0 +1,9 @@ +import nl.adaptivity.js.util.asElement +import nl.adaptivity.xmlutil.dom.Element +import nl.adaptivity.xmlutil.dom.Node + +@Suppress("UNCHECKED_CAST_TO_EXTERNAL_INTERFACE") +internal actual fun Sequence.filterIsElement(): Sequence = + mapNotNull { + (this as org.w3c.dom.Node).asElement() as Element + } \ No newline at end of file diff --git a/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt b/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt index 94575a8d..9d0e390f 100644 --- a/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt +++ b/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt @@ -67,7 +67,7 @@ internal fun Element.parseVectorRoot(density: Density): ImageVector { private fun Element.parseVectorNodes(builder: ImageVector.Builder, context: BuildContext) { childrenSequence - .filterIsInstance() + .filterIsElement() .forEach { it.parseVectorNode(builder, context) } @@ -139,7 +139,7 @@ private fun parseStringBrush(str: String) = SolidColor(Color(parseColorValue(str private fun Element.parseElementBrush(): Brush? = childrenSequence - .filterIsInstance() + .filterIsElement() .find { it.nodeName == "gradient" } ?.parseGradient() @@ -188,7 +188,7 @@ private fun Element.parseSweepGradient() = Brush.sweepGradient( private fun Element.parseColorStops(): Array> { val items = childrenSequence - .filterIsInstance() + .filterIsElement() .filter { it.nodeName == "item" } .toList() @@ -253,7 +253,7 @@ private fun Element.apptAttr( ): Element? { val prefix = lookupPrefix(namespace) ?: return null return childrenSequence - .filterIsInstance() + .filterIsElement() .find { it.namespaceURI == AAPT_NS && it.localName == "attr" && it.getAttribute("name") == "$prefix:$name" diff --git a/kamel-image/src/nonJvmMain/kotlin/filterIsElement.kt b/kamel-image/src/nonJvmMain/kotlin/filterIsElement.kt new file mode 100644 index 00000000..4e59eeca --- /dev/null +++ b/kamel-image/src/nonJvmMain/kotlin/filterIsElement.kt @@ -0,0 +1,4 @@ +import nl.adaptivity.xmlutil.dom.Element +import nl.adaptivity.xmlutil.dom.Node + +internal expect fun Sequence.filterIsElement(): Sequence diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt index 866a1c67..9685fbe3 100644 --- a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt @@ -2,9 +2,9 @@ package io.kamel.samples import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier -import io.kamel.core.ExperimentalKamelApi import io.kamel.core.config.KamelConfig import io.kamel.core.config.takeFrom import io.kamel.core.utils.File @@ -12,8 +12,7 @@ import io.kamel.image.KamelImage import io.kamel.image.config.* import io.kamel.image.lazyPainterResource -@OptIn(ExperimentalKamelApi::class) -@androidx.compose.runtime.Composable +@Composable internal fun FileSample() { val kamelConfig = KamelConfig { takeFrom(KamelConfig.Default) From 332c551521df8f254058cd137b87ce381a9ffcb7 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 00:38:06 -0400 Subject: [PATCH 43/74] improve darwin samples --- ...arwinFileSample.kt => BitmapFileSample.kt} | 7 ++-- .../kotlin/io/kamel/samples/SvgFileSample.kt | 39 +++++++++++++++++++ ...{ImageVectorSample.kt => XmlFileSample.kt} | 2 +- .../kotlin/io/kamel/samples/launcher.kt | 14 +++++-- 4 files changed, 53 insertions(+), 9 deletions(-) rename kamel-samples/src/darwinMain/kotlin/io/kamel/samples/{darwinFileSample.kt => BitmapFileSample.kt} (84%) create mode 100644 kamel-samples/src/darwinMain/kotlin/io/kamel/samples/SvgFileSample.kt rename kamel-samples/src/darwinMain/kotlin/io/kamel/samples/{ImageVectorSample.kt => XmlFileSample.kt} (97%) diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/BitmapFileSample.kt similarity index 84% rename from kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt rename to kamel-samples/src/darwinMain/kotlin/io/kamel/samples/BitmapFileSample.kt index 9685fbe3..6f078653 100644 --- a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/darwinFileSample.kt +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/BitmapFileSample.kt @@ -13,17 +13,16 @@ import io.kamel.image.config.* import io.kamel.image.lazyPainterResource @Composable -internal fun FileSample() { +internal fun BitmapFileSample() { val kamelConfig = KamelConfig { takeFrom(KamelConfig.Default) resourcesFetcher() - imageVectorDecoder() - svgDecoder() + imageBitmapDecoder() } CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { Column { - val file = File(io.kamel.tests.MR.files.Kotlin.path) + val file = File(io.kamel.tests.MR.files.Compose.path) val painterResource = lazyPainterResource(file) KamelImage( diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/SvgFileSample.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/SvgFileSample.kt new file mode 100644 index 00000000..dd7cc5d4 --- /dev/null +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/SvgFileSample.kt @@ -0,0 +1,39 @@ +package io.kamel.samples + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import io.kamel.core.config.KamelConfig +import io.kamel.core.config.takeFrom +import io.kamel.core.utils.File +import io.kamel.image.KamelImage +import io.kamel.image.config.Default +import io.kamel.image.config.LocalKamelConfig +import io.kamel.image.config.resourcesFetcher +import io.kamel.image.config.svgDecoder +import io.kamel.image.lazyPainterResource + +@Composable +internal fun SvgFileSample() { + val kamelConfig = KamelConfig { + takeFrom(KamelConfig.Default) + resourcesFetcher() + svgDecoder() + } + + CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { + Column { + val file = File(io.kamel.tests.MR.files.Kotlin.path) + val painterResource = lazyPainterResource(file) + + KamelImage( + painterResource, + contentDescription = "Kotlin", + modifier = Modifier.fillMaxSize(), + onFailure = { throw it } + ) + } + } +} diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/ImageVectorSample.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/XmlFileSample.kt similarity index 97% rename from kamel-samples/src/darwinMain/kotlin/io/kamel/samples/ImageVectorSample.kt rename to kamel-samples/src/darwinMain/kotlin/io/kamel/samples/XmlFileSample.kt index fff2fd32..f52c6488 100644 --- a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/ImageVectorSample.kt +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/XmlFileSample.kt @@ -15,7 +15,7 @@ import io.kamel.image.lazyPainterResource import io.kamel.tests.MR @androidx.compose.runtime.Composable -internal fun ImageVectorSample() { +internal fun XmlFileSample() { val kamelConfig = KamelConfig { takeFrom(KamelConfig.Default) resourcesFetcher() diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt index 3c926f70..0f5e070d 100644 --- a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt @@ -22,18 +22,24 @@ public fun launcher(){ Button({ sampleIndex = 1 }) { - Text("FileSample") + Text("Bitmap") } Button({ sampleIndex = 2 }) { - Text("ImageVectorSample") + Text("Svg") + } + Button({ + sampleIndex = 1 + }) { + Text("Xml") } } when (sampleIndex) { 0 -> Gallery() - 1 -> FileSample() - 2 -> ImageVectorSample() + 1 -> BitmapFileSample() + 2 -> SvgFileSample() + 3 -> XmlFileSample() else -> Text("Invalid Sample Index") } } From 83ff5b2844ab66fd13f09177161185d87efcc501 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 01:04:14 -0400 Subject: [PATCH 44/74] fix packaging resources files for kamel-samples web copy resources from kamel-tests into the proper directory for kamel-samples so they are packaged for the web app --- kamel-samples/build.gradle.kts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index 535d3f3f..f2ecd073 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -217,6 +217,17 @@ project.tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile::class.ja ) } +// todo: remove after https://github.com/icerockdev/moko-resources/issues/392 resolved +// copy resources from kamel-tests into the proper directory for kamel-samples so they are packaged for +// the web app +tasks.register("jsCopyResourcesFromKamelTests") { + from("../kamel-tests/build/generated/moko/jsMain/iokameltests/res") + into("build/generated/moko/jsMain/iokamelsamples/res") +} +tasks.getByName("jsProcessResources").dependsOn("jsCopyResourcesFromKamelTests") +tasks.getByName("jsCopyResourcesFromKamelTests").dependsOn(":kamel-tests:generateMRjsMain") + + // todo: Remove when resolved: https://github.com/icerockdev/moko-resources/issues/372 tasks.withType() .matching { linkTask -> linkTask.binary is AbstractExecutable } From 9eae3c25e5e1abbca575dee6d8ee271dfc02eb9b Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 14:54:44 -0400 Subject: [PATCH 45/74] fix visibility --- .../src/jsMain/kotlin/io/kamel/core/utils/Platform.kt | 4 ++-- .../src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt index d2955d7a..e3755a56 100644 --- a/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt @@ -6,8 +6,8 @@ import kotlinx.coroutines.Dispatchers internal actual val Dispatchers.kamel: CoroutineDispatcher get() = Default -internal actual typealias File = org.w3c.files.File +public actual typealias File = org.w3c.files.File -internal actual typealias URL = org.w3c.dom.url.URL +public actual typealias URL = org.w3c.dom.url.URL public actual class URI(public val uri: String) \ No newline at end of file diff --git a/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt b/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt index 18ff9fcf..e95c1ded 100644 --- a/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt +++ b/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt @@ -7,8 +7,8 @@ import java.net.URL internal actual val Dispatchers.kamel: CoroutineDispatcher get() = IO -internal actual typealias File = java.io.File +public actual typealias File = java.io.File -internal actual typealias URL = URL +public actual typealias URL = URL -internal actual typealias URI = URI \ No newline at end of file +public actual typealias URI = URI \ No newline at end of file From 65a5a4a1a1374c1cb9434800791ee6188b441b9f Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 15:08:43 -0400 Subject: [PATCH 46/74] androidSourceSetLayoutVersion=2 --- gradle.properties | 2 ++ kamel-image/build.gradle.kts | 22 ++-------------------- kamel-samples/build.gradle.kts | 17 ----------------- 3 files changed, 4 insertions(+), 37 deletions(-) diff --git a/gradle.properties b/gradle.properties index f552389c..cefec6eb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,9 @@ kotlin.code.style=official kotlin.native.cacheKind=none kotlin.native.useEmbeddableCompilerJar=true kotlin.mpp.enableCInteropCommonization=true +kotlin.mpp.androidSourceSetLayoutVersion=2 compose.desktop.verbose=true + android.useAndroidX=true android.disableAutomaticComponentCreation=true kotlin.mpp.stability.nowarn=true diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 803e6385..1e022d1f 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.compose.compose import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode plugins { @@ -14,7 +13,6 @@ android { defaultConfig { minSdk = 21 - targetSdk = 33 multiDexEnabled = true } @@ -29,22 +27,6 @@ android { } } - sourceSets { - named("main") { - manifest.srcFile("src/androidMain/AndroidManifest.xml") - res.srcDirs("src/androidMain/res", "src/commonMain/resources") - } - } - - configurations { - create("androidTestApi") - create("androidTestDebugApi") - create("androidTestReleaseApi") - create("testApi") - create("testDebugApi") - create("testReleaseApi") - } - } kotlin { @@ -110,13 +92,13 @@ kotlin { dependsOn(jvmMain) } - val androidTest by getting { + val androidUnitTest by getting { dependsOn(jvmTest) } val nonJvmMain by creating { dependsOn(commonMain) - dependencies{ + dependencies { implementation("io.github.pdvrieze.xmlutil:serialization:0.86.0") } } diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index f2ecd073..d6655092 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.compose.compose import org.jetbrains.compose.desktop.application.tasks.AbstractNativeMacApplicationPackageAppDirTask import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractExecutable @@ -38,22 +37,6 @@ android { excludes += setOf("META-INF/AL2.0", "META-INF/LGPL2.1") } } - - sourceSets { - named("main") { - manifest.srcFile("src/androidMain/AndroidManifest.xml") - res.srcDirs("src/androidMain/res", "src/commonMain/resources") - } - } - - configurations { - create("androidTestApi") - create("androidTestDebugApi") - create("androidTestReleaseApi") - create("testApi") - create("testDebugApi") - create("testReleaseApi") - } } kotlin { From 615684e98440080f96ffb37a2364a5a3fa066833 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 15:34:44 -0400 Subject: [PATCH 47/74] fix packaging resouces files on jvm --- kamel-samples/build.gradle.kts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index d6655092..98287456 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -210,6 +210,13 @@ tasks.register("jsCopyResourcesFromKamelTests") { tasks.getByName("jsProcessResources").dependsOn("jsCopyResourcesFromKamelTests") tasks.getByName("jsCopyResourcesFromKamelTests").dependsOn(":kamel-tests:generateMRjsMain") +tasks.register("desktopCopyResourcesFromKamelTests") { + from("../kamel-tests/build/generated/moko/jvmMain/iokameltests/res") + into("build/generated/moko/desktopMain/iokamelsamples/res") +} +tasks.getByName("desktopProcessResources").dependsOn("desktopCopyResourcesFromKamelTests") +tasks.getByName("desktopCopyResourcesFromKamelTests").dependsOn(":kamel-tests:generateMRjvmMain") + // todo: Remove when resolved: https://github.com/icerockdev/moko-resources/issues/372 tasks.withType() From f13392c99284de0713c89ace67c352e30fcb9d1e Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 15:40:40 -0400 Subject: [PATCH 48/74] commonize sample. fix android build downgrade MokoResources due to android issue --- buildSrc/src/main/kotlin/Dependencies.kt | 2 +- kamel-samples/build.gradle.kts | 4 + .../kotlin/io/kamel/samples/AndroidSample.kt | 17 +- .../io/kamel/samples/ResourcesSample.kt | 47 ----- .../kotlin/io/kamel/samples/getFile.kt | 24 +++ .../kotlin/io/kamel/samples/FileSample.kt | 25 +-- .../kotlin/io/kamel/samples/getFile.kt | 7 + .../kotlin/io/kamel/samples/launcher.kt | 13 +- .../io/kamel/samples/BitmapFileSample.kt | 36 ---- .../kotlin/io/kamel/samples/SvgFileSample.kt | 39 ----- .../kotlin/io/kamel/samples/XmlFileSample.kt | 39 ----- .../kotlin/io/kamel/samples/getFile.kt | 9 + .../kotlin/io/kamel/samples/DesktopSample.kt | 17 +- .../kotlin/io/kamel/samples/FileSample.kt | 36 ---- .../kotlin/io/kamel/samples/getFile.kt | 20 +++ .../jsMain/kotlin/io/kamel/samples/getFile.kt | 14 ++ kamel-samples/src/jsMain/kotlin/main.js.kt | 39 ++--- .../src/macosMain/kotlin/main.macos.kt | 12 +- .../src/uikitMain/kotlin/main.uikit.kt | 12 +- kamel-tests/build.gradle.kts | 27 ++- .../src/androidMain/AndroidManifest.xml | 2 + .../kotlin/io/kamel/tests/AndroidTestUtils.kt | 17 ++ kotlin-js-store/yarn.lock | 162 ++++++------------ 23 files changed, 254 insertions(+), 366 deletions(-) delete mode 100644 kamel-samples/src/androidMain/kotlin/io/kamel/samples/ResourcesSample.kt create mode 100644 kamel-samples/src/androidMain/kotlin/io/kamel/samples/getFile.kt rename kamel-samples/src/{jsMain => commonMain}/kotlin/io/kamel/samples/FileSample.kt (55%) create mode 100644 kamel-samples/src/commonMain/kotlin/io/kamel/samples/getFile.kt rename kamel-samples/src/{darwinMain => commonMain}/kotlin/io/kamel/samples/launcher.kt (73%) delete mode 100644 kamel-samples/src/darwinMain/kotlin/io/kamel/samples/BitmapFileSample.kt delete mode 100644 kamel-samples/src/darwinMain/kotlin/io/kamel/samples/SvgFileSample.kt delete mode 100644 kamel-samples/src/darwinMain/kotlin/io/kamel/samples/XmlFileSample.kt create mode 100644 kamel-samples/src/darwinMain/kotlin/io/kamel/samples/getFile.kt delete mode 100644 kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt create mode 100644 kamel-samples/src/desktopMain/kotlin/io/kamel/samples/getFile.kt create mode 100644 kamel-samples/src/jsMain/kotlin/io/kamel/samples/getFile.kt create mode 100644 kamel-tests/src/androidMain/AndroidManifest.xml create mode 100644 kamel-tests/src/androidMain/kotlin/io/kamel/tests/AndroidTestUtils.kt diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 189b2683..9b9ea741 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -47,7 +47,7 @@ object Versions { const val Coroutines = "1.7.0" const val Compose = "1.4.0" const val AGP = "7.4.2" - const val MokoResources = "0.22.0" + const val MokoResources = "0.20.1" object Android { const val ActivityCompose = "1.7.1" diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index 98287456..db2bd5b6 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -217,6 +217,10 @@ tasks.register("desktopCopyResourcesFromKamelTests") { tasks.getByName("desktopProcessResources").dependsOn("desktopCopyResourcesFromKamelTests") tasks.getByName("desktopCopyResourcesFromKamelTests").dependsOn(":kamel-tests:generateMRjvmMain") +tasks.findByName("desktopProcessResources")!!.dependsOn("generateMRcommonMain") +tasks.findByName("desktopProcessResources")!!.dependsOn("generateMRdesktopMain") +tasks.findByName("jsProcessResources")!!.dependsOn("generateMRcommonMain") +tasks.findByName("jsProcessResources")!!.dependsOn("generateMRjsMain") // todo: Remove when resolved: https://github.com/icerockdev/moko-resources/issues/372 tasks.withType() diff --git a/kamel-samples/src/androidMain/kotlin/io/kamel/samples/AndroidSample.kt b/kamel-samples/src/androidMain/kotlin/io/kamel/samples/AndroidSample.kt index 092aa949..3f0e4d64 100644 --- a/kamel-samples/src/androidMain/kotlin/io/kamel/samples/AndroidSample.kt +++ b/kamel-samples/src/androidMain/kotlin/io/kamel/samples/AndroidSample.kt @@ -3,6 +3,12 @@ package io.kamel.samples import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity +import androidx.compose.runtime.remember +import io.kamel.core.config.KamelConfig +import io.kamel.core.config.takeFrom +import io.kamel.image.config.Default +import io.kamel.image.config.imageBitmapDecoder +import io.kamel.image.config.resourcesFetcher public actual val cellsCount: Int = 2 @@ -11,7 +17,16 @@ class AndroidSample : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - Gallery() + val kamelConfig = remember { + KamelConfig { + takeFrom(KamelConfig.Default) + resourcesFetcher(this@AndroidSample) +// imageVectorDecoder() +// svgDecsoder() + imageBitmapDecoder() + } + } + launcher(kamelConfig, applicationContext) } } diff --git a/kamel-samples/src/androidMain/kotlin/io/kamel/samples/ResourcesSample.kt b/kamel-samples/src/androidMain/kotlin/io/kamel/samples/ResourcesSample.kt deleted file mode 100644 index 26d05718..00000000 --- a/kamel-samples/src/androidMain/kotlin/io/kamel/samples/ResourcesSample.kt +++ /dev/null @@ -1,47 +0,0 @@ -package io.kamel.samples - -import android.os.Bundle -import androidx.activity.compose.setContent -import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import io.kamel.core.config.KamelConfig -import io.kamel.core.config.takeFrom -import io.kamel.image.KamelImage -import io.kamel.image.config.Default -import io.kamel.image.config.LocalKamelConfig -import io.kamel.image.config.resourcesFetcher -import io.kamel.image.config.resourcesIdMapper -import io.kamel.image.lazyPainterResource - -class ResourcesSample : AppCompatActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContent { - - val context = LocalContext.current - - val androidConfig = KamelConfig { - takeFrom(KamelConfig.Default) - resourcesFetcher(context) - resourcesIdMapper(context) - } - - CompositionLocalProvider(LocalKamelConfig provides androidConfig) { - - val imageResource = lazyPainterResource(R.raw.compose) - - KamelImage( - resource = imageResource, - contentDescription = "Compose", - modifier = Modifier.fillMaxSize(), - ) - - } - - } - } -} \ No newline at end of file diff --git a/kamel-samples/src/androidMain/kotlin/io/kamel/samples/getFile.kt b/kamel-samples/src/androidMain/kotlin/io/kamel/samples/getFile.kt new file mode 100644 index 00000000..88150acc --- /dev/null +++ b/kamel-samples/src/androidMain/kotlin/io/kamel/samples/getFile.kt @@ -0,0 +1,24 @@ +package io.kamel.samples + +import android.content.Context +import android.content.res.Resources +import dev.icerock.moko.resources.AssetResource +import dev.icerock.moko.resources.FileResource +import io.kamel.core.utils.File +import java.io.FileOutputStream +import java.io.InputStream + +public actual suspend fun getFile(fileResource: FileResource, context: Any?): File { + val file = java.io.File.createTempFile("temp", null) + val resources: Resources = (context as Context).resources + val ins: InputStream = resources.openRawResource(fileResource.rawResId) + FileOutputStream(file).use { os -> + val buffer = ByteArray(4096) + var length: Int + while (ins.read(buffer).also { length = it } > 0) { + os.write(buffer, 0, length) + } + os.flush() + } + return file +} \ No newline at end of file diff --git a/kamel-samples/src/jsMain/kotlin/io/kamel/samples/FileSample.kt b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/FileSample.kt similarity index 55% rename from kamel-samples/src/jsMain/kotlin/io/kamel/samples/FileSample.kt rename to kamel-samples/src/commonMain/kotlin/io/kamel/samples/FileSample.kt index 271b4087..c82e2fc8 100644 --- a/kamel-samples/src/jsMain/kotlin/io/kamel/samples/FileSample.kt +++ b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/FileSample.kt @@ -2,42 +2,27 @@ package io.kamel.samples import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import dev.icerock.moko.resources.FileResource import io.kamel.core.config.KamelConfig -import io.kamel.core.config.takeFrom +import io.kamel.core.utils.File import io.kamel.image.KamelImage -import io.kamel.image.config.Default import io.kamel.image.config.LocalKamelConfig -import io.kamel.image.config.imageVectorDecoder -import io.kamel.image.config.resourcesFetcher import io.kamel.image.lazyPainterResource -import io.ktor.utils.io.core.* -import kotlinx.browser.window -import kotlinx.coroutines.await import kotlinx.coroutines.launch -import org.w3c.files.File + @Composable -internal fun FileSample() { +internal fun FileSample(fileResource: FileResource, kamelConfig: KamelConfig, context: Any? = null) { val scope = rememberCoroutineScope() var file: File? by remember { mutableStateOf(null) } scope.launch { - val blob = window.fetch(io.kamel.tests.MR.files.Compose.fileUrl).await().blob().await() - file = File( - arrayOf(blob), - io.kamel.tests.MR.files.Compose.fileUrl - ) + file = getFile(fileResource, context) } - val kamelConfig = KamelConfig { - takeFrom(KamelConfig.Default) - resourcesFetcher() - imageVectorDecoder() - } CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { Column { diff --git a/kamel-samples/src/commonMain/kotlin/io/kamel/samples/getFile.kt b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/getFile.kt new file mode 100644 index 00000000..63930b15 --- /dev/null +++ b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/getFile.kt @@ -0,0 +1,7 @@ +package io.kamel.samples + +import dev.icerock.moko.resources.AssetResource +import dev.icerock.moko.resources.FileResource +import io.kamel.core.utils.File + +public expect suspend fun getFile(fileResource: FileResource, context: Any? = null): File \ No newline at end of file diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/launcher.kt similarity index 73% rename from kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt rename to kamel-samples/src/commonMain/kotlin/io/kamel/samples/launcher.kt index 0f5e070d..06f20b97 100644 --- a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/launcher.kt +++ b/kamel-samples/src/commonMain/kotlin/io/kamel/samples/launcher.kt @@ -8,9 +8,11 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import io.kamel.core.config.KamelConfig +import io.kamel.tests.MR @androidx.compose.runtime.Composable -public fun launcher(){ +public fun launcher(kamelConfig: KamelConfig, context: Any? = null) { var sampleIndex by remember { mutableStateOf(0) } Column { Row { @@ -30,16 +32,17 @@ public fun launcher(){ Text("Svg") } Button({ - sampleIndex = 1 + sampleIndex = 3 }) { Text("Xml") } } when (sampleIndex) { 0 -> Gallery() - 1 -> BitmapFileSample() - 2 -> SvgFileSample() - 3 -> XmlFileSample() + 1 -> FileSample(MR.files.Compose, kamelConfig, context) + 2 -> FileSample(MR.files.Kotlin, kamelConfig, context) + 3 -> FileSample(MR.files.ComposeXml, kamelConfig, context) + else -> Text("Invalid Sample Index") } } diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/BitmapFileSample.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/BitmapFileSample.kt deleted file mode 100644 index 6f078653..00000000 --- a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/BitmapFileSample.kt +++ /dev/null @@ -1,36 +0,0 @@ -package io.kamel.samples - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Modifier -import io.kamel.core.config.KamelConfig -import io.kamel.core.config.takeFrom -import io.kamel.core.utils.File -import io.kamel.image.KamelImage -import io.kamel.image.config.* -import io.kamel.image.lazyPainterResource - -@Composable -internal fun BitmapFileSample() { - val kamelConfig = KamelConfig { - takeFrom(KamelConfig.Default) - resourcesFetcher() - imageBitmapDecoder() - } - - CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { - Column { - val file = File(io.kamel.tests.MR.files.Compose.path) - val painterResource = lazyPainterResource(file) - - KamelImage( - painterResource, - contentDescription = "Kotlin", - modifier = Modifier.fillMaxSize(), - onFailure = { throw it } - ) - } - } -} diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/SvgFileSample.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/SvgFileSample.kt deleted file mode 100644 index dd7cc5d4..00000000 --- a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/SvgFileSample.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.kamel.samples - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Modifier -import io.kamel.core.config.KamelConfig -import io.kamel.core.config.takeFrom -import io.kamel.core.utils.File -import io.kamel.image.KamelImage -import io.kamel.image.config.Default -import io.kamel.image.config.LocalKamelConfig -import io.kamel.image.config.resourcesFetcher -import io.kamel.image.config.svgDecoder -import io.kamel.image.lazyPainterResource - -@Composable -internal fun SvgFileSample() { - val kamelConfig = KamelConfig { - takeFrom(KamelConfig.Default) - resourcesFetcher() - svgDecoder() - } - - CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { - Column { - val file = File(io.kamel.tests.MR.files.Kotlin.path) - val painterResource = lazyPainterResource(file) - - KamelImage( - painterResource, - contentDescription = "Kotlin", - modifier = Modifier.fillMaxSize(), - onFailure = { throw it } - ) - } - } -} diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/XmlFileSample.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/XmlFileSample.kt deleted file mode 100644 index f52c6488..00000000 --- a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/XmlFileSample.kt +++ /dev/null @@ -1,39 +0,0 @@ -package io.kamel.samples - -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Modifier -import io.kamel.core.config.KamelConfig -import io.kamel.core.config.takeFrom -import io.kamel.core.utils.File -import io.kamel.image.KamelImage -import io.kamel.image.config.Default -import io.kamel.image.config.LocalKamelConfig -import io.kamel.image.config.imageVectorDecoder -import io.kamel.image.config.resourcesFetcher -import io.kamel.image.lazyPainterResource -import io.kamel.tests.MR - -@androidx.compose.runtime.Composable -internal fun XmlFileSample() { - val kamelConfig = KamelConfig { - takeFrom(KamelConfig.Default) - resourcesFetcher() - imageVectorDecoder() - } - - CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { - val file = File(MR.files.ComposeXml.path) - val painterResource = lazyPainterResource(file) - - KamelImage( - painterResource, - contentDescription = "Compose", - modifier = Modifier.fillMaxSize(), - onFailure = { throw it }, - onLoading = { - println(it) - } - ) - } -} \ No newline at end of file diff --git a/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/getFile.kt b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/getFile.kt new file mode 100644 index 00000000..b9c210a8 --- /dev/null +++ b/kamel-samples/src/darwinMain/kotlin/io/kamel/samples/getFile.kt @@ -0,0 +1,9 @@ +package io.kamel.samples + +import dev.icerock.moko.resources.FileResource +import io.kamel.core.utils.File +import io.kamel.tests.MR + +public actual suspend fun getFile(fileResource: FileResource, context: Any?): File { + return File(fileResource.path) +} \ No newline at end of file diff --git a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/DesktopSample.kt b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/DesktopSample.kt index fcad554d..871c8b87 100644 --- a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/DesktopSample.kt +++ b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/DesktopSample.kt @@ -1,7 +1,22 @@ package io.kamel.samples +import androidx.compose.runtime.remember import androidx.compose.ui.window.singleWindowApplication +import io.kamel.core.config.KamelConfig +import io.kamel.core.config.takeFrom +import io.kamel.image.config.* public actual val cellsCount: Int = 4 -public fun main(): Unit = singleWindowApplication { Gallery() } \ No newline at end of file +public fun main(): Unit = singleWindowApplication { + val kamelConfig = remember { + KamelConfig { + takeFrom(KamelConfig.Default) + resourcesFetcher() + imageVectorDecoder() + svgDecoder() + imageBitmapDecoder() + } + } + launcher(kamelConfig) +} \ No newline at end of file diff --git a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt deleted file mode 100644 index 7d856938..00000000 --- a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/FileSample.kt +++ /dev/null @@ -1,36 +0,0 @@ -package io.kamel.samples - -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Modifier -import androidx.compose.ui.window.singleWindowApplication -import io.kamel.core.config.KamelConfig -import io.kamel.core.config.takeFrom -import io.kamel.image.KamelImage -import io.kamel.image.config.Default -import io.kamel.image.config.LocalKamelConfig -import io.kamel.image.config.imageVectorDecoder -import io.kamel.image.config.resourcesFetcher -import io.kamel.image.lazyPainterResource -import java.io.File -import io.kamel.tests.MR - -public fun main(): Unit = singleWindowApplication { - val kamelConfig = KamelConfig { - takeFrom(KamelConfig.Default) - resourcesFetcher() - imageVectorDecoder() - } - - CompositionLocalProvider(LocalKamelConfig provides kamelConfig) { - val painterResource = - lazyPainterResource(File(MR.files.Compose.filePath)) - - KamelImage( - painterResource, - contentDescription = "Compose", - modifier = Modifier.fillMaxSize(), - onFailure = { throw it } - ) - } -} \ No newline at end of file diff --git a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/getFile.kt b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/getFile.kt new file mode 100644 index 00000000..c75b1a06 --- /dev/null +++ b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/getFile.kt @@ -0,0 +1,20 @@ +package io.kamel.samples + +import dev.icerock.moko.resources.FileResource +import io.kamel.core.utils.File +import java.io.FileOutputStream + + +public actual suspend fun getFile(fileResource: FileResource, context: Any?): File { + val file = java.io.File.createTempFile("temp", null) + val ins = Thread.currentThread().contextClassLoader.getResource(fileResource.filePath).openStream() + FileOutputStream(file).use { os -> + val buffer = ByteArray(4096) + var length: Int + while (ins.read(buffer).also { length = it } > 0) { + os.write(buffer, 0, length) + } + os.flush() + } + return file +} \ No newline at end of file diff --git a/kamel-samples/src/jsMain/kotlin/io/kamel/samples/getFile.kt b/kamel-samples/src/jsMain/kotlin/io/kamel/samples/getFile.kt new file mode 100644 index 00000000..7378f6e5 --- /dev/null +++ b/kamel-samples/src/jsMain/kotlin/io/kamel/samples/getFile.kt @@ -0,0 +1,14 @@ +package io.kamel.samples + +import dev.icerock.moko.resources.FileResource +import io.kamel.core.utils.File +import kotlinx.browser.window +import kotlinx.coroutines.await + +public actual suspend fun getFile(fileResource: FileResource, context: Any?): File { + val blob = window.fetch(fileResource.fileUrl).await().blob().await() + return org.w3c.files.File( + arrayOf(blob), + io.kamel.tests.MR.files.Compose.fileUrl + ) +} \ No newline at end of file diff --git a/kamel-samples/src/jsMain/kotlin/main.js.kt b/kamel-samples/src/jsMain/kotlin/main.js.kt index 08f11fec..157e6ac6 100644 --- a/kamel-samples/src/jsMain/kotlin/main.js.kt +++ b/kamel-samples/src/jsMain/kotlin/main.js.kt @@ -1,41 +1,26 @@ -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.Button -import androidx.compose.material.Text import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier import androidx.compose.ui.window.Window -import io.kamel.samples.FileSample -import io.kamel.samples.Gallery +import io.kamel.core.config.KamelConfig +import io.kamel.core.config.takeFrom +import io.kamel.image.config.* +import io.kamel.samples.launcher import org.jetbrains.skiko.wasm.onWasmReady public fun main() { + val kamelConfig = KamelConfig { + takeFrom(KamelConfig.Default) + resourcesFetcher() + imageVectorDecoder() + svgDecoder() + imageBitmapDecoder() + } onWasmReady { Window("Sample") { var sampleIndex by remember { mutableStateOf(0) } - Column(modifier = Modifier.fillMaxSize()) { - Row { - Button({ - sampleIndex = 0 - }) { - Text("Gallery") - } - Button({ - sampleIndex = 1 - }) { - Text("FileSample") - } - } - when (sampleIndex) { - 0 -> Gallery() - 1 -> FileSample() - else -> Text("Invalid Sample Index") - } - } + launcher(kamelConfig) } } } \ No newline at end of file diff --git a/kamel-samples/src/macosMain/kotlin/main.macos.kt b/kamel-samples/src/macosMain/kotlin/main.macos.kt index 25a086c0..c528060a 100644 --- a/kamel-samples/src/macosMain/kotlin/main.macos.kt +++ b/kamel-samples/src/macosMain/kotlin/main.macos.kt @@ -1,12 +1,22 @@ import androidx.compose.ui.window.Window +import io.kamel.core.config.KamelConfig +import io.kamel.core.config.takeFrom +import io.kamel.image.config.* import io.kamel.samples.launcher import platform.AppKit.NSApp import platform.AppKit.NSApplication public fun main() { NSApplication.sharedApplication() + val kamelConfig = KamelConfig { + takeFrom(KamelConfig.Default) + resourcesFetcher() + imageVectorDecoder() + svgDecoder() + imageBitmapDecoder() + } Window("Sample") { - launcher() + launcher(kamelConfig) } NSApp?.run() } \ No newline at end of file diff --git a/kamel-samples/src/uikitMain/kotlin/main.uikit.kt b/kamel-samples/src/uikitMain/kotlin/main.uikit.kt index 6e0e9e0d..a1dd3e4c 100644 --- a/kamel-samples/src/uikitMain/kotlin/main.uikit.kt +++ b/kamel-samples/src/uikitMain/kotlin/main.uikit.kt @@ -3,6 +3,9 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.ui.unit.dp import androidx.compose.ui.Modifier +import io.kamel.core.config.KamelConfig +import io.kamel.core.config.takeFrom +import io.kamel.image.config.* import io.kamel.samples.launcher import kotlinx.cinterop.autoreleasepool import kotlinx.cinterop.cstr @@ -36,9 +39,16 @@ class SkikoAppDelegate : UIResponder, UIApplicationDelegateProtocol { override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map?): Boolean { window = UIWindow(frame = UIScreen.mainScreen.bounds) + val kamelConfig = KamelConfig { + takeFrom(KamelConfig.Default) + resourcesFetcher() + imageVectorDecoder() + svgDecoder() + imageBitmapDecoder() + } window!!.rootViewController = Application("Sample") { Column(Modifier.padding(top = 30.dp)) { - launcher() + launcher(kamelConfig) } } window!!.makeKeyAndVisible() diff --git a/kamel-tests/build.gradle.kts b/kamel-tests/build.gradle.kts index 3abae161..22c87434 100644 --- a/kamel-tests/build.gradle.kts +++ b/kamel-tests/build.gradle.kts @@ -1,10 +1,12 @@ plugins { + `android-library` multiplatform mokoResources } kotlin { jvm() + android() js(IR) { browser() } @@ -46,9 +48,32 @@ kotlin { } } +android { + compileSdk = 33 + + defaultConfig { + minSdk = 16 + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + defaultConfig { + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + //https://github.com/icerockdev/moko-resources/issues/403 + sourceSets["main"].res.srcDir(File(buildDir, "generated/moko/androidMain/res")) +} + + multiplatformResources { multiplatformResourcesPackage = "io.kamel.tests" } tasks.findByName("jvmProcessResources")!!.dependsOn("generateMRcommonMain") -tasks.findByName("jvmProcessResources")!!.dependsOn("generateMRjvmMain") \ No newline at end of file +tasks.findByName("jvmProcessResources")!!.dependsOn("generateMRjvmMain") +tasks.findByName("jsProcessResources")!!.dependsOn("generateMRcommonMain") +tasks.findByName("jsProcessResources")!!.dependsOn("generateMRjsMain") \ No newline at end of file diff --git a/kamel-tests/src/androidMain/AndroidManifest.xml b/kamel-tests/src/androidMain/AndroidManifest.xml new file mode 100644 index 00000000..17e5f52a --- /dev/null +++ b/kamel-tests/src/androidMain/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/kamel-tests/src/androidMain/kotlin/io/kamel/tests/AndroidTestUtils.kt b/kamel-tests/src/androidMain/kotlin/io/kamel/tests/AndroidTestUtils.kt new file mode 100644 index 00000000..f89696e3 --- /dev/null +++ b/kamel-tests/src/androidMain/kotlin/io/kamel/tests/AndroidTestUtils.kt @@ -0,0 +1,17 @@ +package io.kamel.tests + +import io.ktor.utils.io.* +import io.ktor.utils.io.core.* + + +actual suspend fun resourceImage(): ByteReadChannel { + TODO() +// val bytes = MR.assets.Compose.readText().encodeToByteArray() +// return ByteReadChannel(bytes) +} + +actual suspend fun svgImage(): ByteReadChannel { + TODO() +// val bytes = MR.files.Kotlin.readText().encodeToByteArray() +// return ByteReadChannel(bytes) +} diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 10befde4..ead26e82 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -637,6 +637,11 @@ bcp-47@1.0.8: is-alphanumerical "^1.0.0" is-decimal "^1.0.0" +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -933,25 +938,6 @@ cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -css-loader@6.7.3: - version "6.7.3" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.3.tgz#1e8799f3ccc5874fdd55461af51137fcc5befbcd" - integrity sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ== - dependencies: - icss-utils "^5.1.0" - postcss "^8.4.19" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.0" - postcss-modules-scope "^3.0.0" - postcss-modules-values "^4.0.0" - postcss-value-parser "^4.2.0" - semver "^7.3.8" - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - custom-event@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" @@ -1078,6 +1064,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -1281,6 +1272,14 @@ faye-websocket@^0.11.3: dependencies: websocket-driver ">=0.5.1" +file-loader@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -1571,11 +1570,6 @@ iconv-lite@^0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -icss-utils@^5.0.0, icss-utils@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" - integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== - import-local@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" @@ -1801,6 +1795,11 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== +json5@^2.1.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -1878,6 +1877,15 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== +loader-utils@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -1916,13 +1924,6 @@ log4js@^6.4.1: rfdc "^1.3.0" streamroller "^3.1.2" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - magic-string@^0.25.7: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -2002,13 +2003,6 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mini-css-extract-plugin@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz#9a1251d15f2035c342d99a468ab9da7a0451b71e" - integrity sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg== - dependencies: - schema-utils "^4.0.0" - minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -2101,11 +2095,6 @@ nanoid@3.3.3: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== -nanoid@^3.3.6: - version "3.3.6" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" - integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== - negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -2290,56 +2279,6 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== - -postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== - dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" - -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== - dependencies: - postcss-selector-parser "^6.0.4" - -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== - dependencies: - icss-utils "^5.0.0" - -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: - version "6.0.12" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.12.tgz#2efae5ffab3c8bfb2b7fbf0c426e3bca616c4abb" - integrity sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== - -postcss@^8.4.19: - version "8.4.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.23.tgz#df0aee9ac7c5e53e1075c24a3613496f9e6552ab" - integrity sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA== - dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -2535,6 +2474,15 @@ safe-identifier@^0.4.1: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +schema-utils@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.2.tgz#36c10abca6f7577aeae136c804b0c741edeadc99" + integrity sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + schema-utils@^3.1.0, schema-utils@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" @@ -2566,13 +2514,6 @@ selfsigned@^2.0.1: dependencies: node-forge "^1" -semver@^7.3.8: - version "7.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.0.tgz#ed8c5dc8efb6c629c88b23d41dc9bf40c1d96cd0" - integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA== - dependencies: - lru-cache "^6.0.0" - send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -2828,11 +2769,6 @@ strip-json-comments@3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -style-loader@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" - integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== - supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -2982,7 +2918,16 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: +url-loader@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" + integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== + dependencies: + loader-utils "^2.0.0" + mime-types "^2.1.27" + schema-utils "^3.0.0" + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -3221,11 +3166,6 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" From 14bbaa55599f0202638ef0fb8c7976e72134b27c Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 15:56:28 -0400 Subject: [PATCH 49/74] jvm: fix tmp file so that lazyPainterResource can pick correct painter --- .../src/desktopMain/kotlin/io/kamel/samples/getFile.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/getFile.kt b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/getFile.kt index c75b1a06..8ea6d9ea 100644 --- a/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/getFile.kt +++ b/kamel-samples/src/desktopMain/kotlin/io/kamel/samples/getFile.kt @@ -6,7 +6,7 @@ import java.io.FileOutputStream public actual suspend fun getFile(fileResource: FileResource, context: Any?): File { - val file = java.io.File.createTempFile("temp", null) + val file = java.io.File.createTempFile("temp", ".${fileResource.filePath.substringAfterLast(".")}") val ins = Thread.currentThread().contextClassLoader.getResource(fileResource.filePath).openStream() FileOutputStream(file).use { os -> val buffer = ByteArray(4096) From 960c3e270d7d8c6564607fa6aa5105e0b8cfe141 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 16:39:50 -0400 Subject: [PATCH 50/74] andrd: fix tmp file so that lazyPainterResource can pick correct painter --- .../src/androidMain/kotlin/io/kamel/samples/getFile.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kamel-samples/src/androidMain/kotlin/io/kamel/samples/getFile.kt b/kamel-samples/src/androidMain/kotlin/io/kamel/samples/getFile.kt index 88150acc..ebb6bb49 100644 --- a/kamel-samples/src/androidMain/kotlin/io/kamel/samples/getFile.kt +++ b/kamel-samples/src/androidMain/kotlin/io/kamel/samples/getFile.kt @@ -2,15 +2,20 @@ package io.kamel.samples import android.content.Context import android.content.res.Resources -import dev.icerock.moko.resources.AssetResource +import android.util.Log +import android.util.TypedValue import dev.icerock.moko.resources.FileResource import io.kamel.core.utils.File import java.io.FileOutputStream import java.io.InputStream + public actual suspend fun getFile(fileResource: FileResource, context: Any?): File { - val file = java.io.File.createTempFile("temp", null) val resources: Resources = (context as Context).resources + val value = TypedValue() + resources.getValue(fileResource.rawResId, value, true) + val name = value.string.toString() + val file = java.io.File.createTempFile("temp", ".${name.substringAfterLast(".")}") val ins: InputStream = resources.openRawResource(fileResource.rawResId) FileOutputStream(file).use { os -> val buffer = ByteArray(4096) From 4ffa1c1fe27d94623ea4d3e447ce40d6a13a2a8b Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 16:41:45 -0400 Subject: [PATCH 51/74] js: fix file so that lazyPainterResource can pick correct painter on js the issue is that toString doesn't print file name. so lazyPainterResource cant pick correct painter unless we override it. and I can't override the external js class toString function. So instead wrap File in a new File class --- .../src/jsMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt | 2 +- .../src/jsMain/kotlin/io/kamel/core/utils/Platform.kt | 7 ++++++- .../src/jsMain/kotlin/io/kamel/samples/getFile.kt | 6 +++--- kamel-samples/src/jsMain/kotlin/main.js.kt | 1 - 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/kamel-core/src/jsMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt b/kamel-core/src/jsMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt index 76b10ef1..c763f3b8 100644 --- a/kamel-core/src/jsMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt +++ b/kamel-core/src/jsMain/kotlin/io/kamel/core/fetcher/FileFetcher.kt @@ -33,7 +33,7 @@ internal actual object FileFetcher : Fetcher { data: File, resourceConfig: ResourceConfig ): Flow> = flow { - val byteReadChannel = ByteReadChannel(getBase64(data)) + val byteReadChannel = ByteReadChannel(getBase64(data.file)) emit(Resource.Success(byteReadChannel, source)) } diff --git a/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt index e3755a56..c53e1238 100644 --- a/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt @@ -6,7 +6,12 @@ import kotlinx.coroutines.Dispatchers internal actual val Dispatchers.kamel: CoroutineDispatcher get() = Default -public actual typealias File = org.w3c.files.File +public actual class File(public val file: org.w3c.files.File) { + override fun toString(): String { + return file.name + } +} + public actual typealias URL = org.w3c.dom.url.URL diff --git a/kamel-samples/src/jsMain/kotlin/io/kamel/samples/getFile.kt b/kamel-samples/src/jsMain/kotlin/io/kamel/samples/getFile.kt index 7378f6e5..25d0c11a 100644 --- a/kamel-samples/src/jsMain/kotlin/io/kamel/samples/getFile.kt +++ b/kamel-samples/src/jsMain/kotlin/io/kamel/samples/getFile.kt @@ -7,8 +7,8 @@ import kotlinx.coroutines.await public actual suspend fun getFile(fileResource: FileResource, context: Any?): File { val blob = window.fetch(fileResource.fileUrl).await().blob().await() - return org.w3c.files.File( + return File(org.w3c.files.File( arrayOf(blob), - io.kamel.tests.MR.files.Compose.fileUrl - ) + fileResource.fileUrl + )) } \ No newline at end of file diff --git a/kamel-samples/src/jsMain/kotlin/main.js.kt b/kamel-samples/src/jsMain/kotlin/main.js.kt index 157e6ac6..1149436e 100644 --- a/kamel-samples/src/jsMain/kotlin/main.js.kt +++ b/kamel-samples/src/jsMain/kotlin/main.js.kt @@ -19,7 +19,6 @@ public fun main() { } onWasmReady { Window("Sample") { - var sampleIndex by remember { mutableStateOf(0) } launcher(kamelConfig) } } From 98dba5d5159d347035c6743223330670e772055b Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 17:07:56 -0400 Subject: [PATCH 52/74] fix js xml --- .../src/darwinMain/kotlin/attributeOrNull.kt | 15 +++++++++++++++ kamel-image/src/jsMain/kotlin/attributeOrNull.kt | 15 +++++++++++++++ kamel-image/src/jsMain/kotlin/filterIsElement.kt | 2 +- .../src/nonJvmMain/kotlin/XmlVectorParser.kt | 8 ++------ kamel-samples/src/jsMain/kotlin/main.js.kt | 4 ---- 5 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 kamel-image/src/darwinMain/kotlin/attributeOrNull.kt create mode 100644 kamel-image/src/jsMain/kotlin/attributeOrNull.kt diff --git a/kamel-image/src/darwinMain/kotlin/attributeOrNull.kt b/kamel-image/src/darwinMain/kotlin/attributeOrNull.kt new file mode 100644 index 00000000..1085ca54 --- /dev/null +++ b/kamel-image/src/darwinMain/kotlin/attributeOrNull.kt @@ -0,0 +1,15 @@ +import nl.adaptivity.xmlutil.dom.Element + +/*** + * Accessing by namespace does not appear to be working with https://github.com/pdvrieze/xmlutil v0.86.0 + * note: on native ":" had to be prepended to name to load attributes 🤷‍ + * todo: figure out how to handle namespaces + */ +internal actual fun Element.attributeOrNull( + @Suppress("UNUSED_PARAMETER") namespace: String, + name: String +): String? { +// val value = getAttributeNS(namespace,":$name") + val value = getAttribute(":$name") + return value?.ifBlank { null } +} \ No newline at end of file diff --git a/kamel-image/src/jsMain/kotlin/attributeOrNull.kt b/kamel-image/src/jsMain/kotlin/attributeOrNull.kt new file mode 100644 index 00000000..927c508e --- /dev/null +++ b/kamel-image/src/jsMain/kotlin/attributeOrNull.kt @@ -0,0 +1,15 @@ +import nl.adaptivity.xmlutil.dom.Element + +/*** + * Accessing by namespace does not appear to be working with https://github.com/pdvrieze/xmlutil v0.86.0 + * note: on native ":" had to be prepended to name to load attributes 🤷‍ + * todo: figure out how to handle namespaces + */ +internal actual fun Element.attributeOrNull( + @Suppress("UNUSED_PARAMETER") namespace: String, + name: String +): String? { +// val value = getAttributeNS(namespace, name) + val value = getAttribute(name) + return value?.ifBlank { null } +} \ No newline at end of file diff --git a/kamel-image/src/jsMain/kotlin/filterIsElement.kt b/kamel-image/src/jsMain/kotlin/filterIsElement.kt index 697ce4d5..ff73947a 100644 --- a/kamel-image/src/jsMain/kotlin/filterIsElement.kt +++ b/kamel-image/src/jsMain/kotlin/filterIsElement.kt @@ -5,5 +5,5 @@ import nl.adaptivity.xmlutil.dom.Node @Suppress("UNCHECKED_CAST_TO_EXTERNAL_INTERFACE") internal actual fun Sequence.filterIsElement(): Sequence = mapNotNull { - (this as org.w3c.dom.Node).asElement() as Element + (it as org.w3c.dom.Node).asElement() as Element? } \ No newline at end of file diff --git a/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt b/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt index 9d0e390f..8a526b4b 100644 --- a/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt +++ b/kamel-image/src/nonJvmMain/kotlin/XmlVectorParser.kt @@ -223,14 +223,10 @@ private fun Element.parseColorStop(defaultOffset: Float): Pair? { /*** * Accessing by namespace does not appear to be working with https://github.com/pdvrieze/xmlutil v0.86.0 - * note: ":" had to be prepended to name to load attributes 🤷‍ + * note: on native ":" had to be prepended to name to load attributes 🤷‍, js works fine without prepending ":" * todo: figure out how to handle namespaces */ -private fun Element.attributeOrNull(@Suppress("UNUSED_PARAMETER") namespace: String, name: String): String? { -// val value = getAttributeNS(namespace,":$name") - val value = getAttribute(":$name") - return value?.ifBlank { null } -} +internal expect fun Element.attributeOrNull(@Suppress("UNUSED_PARAMETER") namespace: String, name: String): String? /** * Attribute of an element can be represented as a separate child: diff --git a/kamel-samples/src/jsMain/kotlin/main.js.kt b/kamel-samples/src/jsMain/kotlin/main.js.kt index 1149436e..db57cb22 100644 --- a/kamel-samples/src/jsMain/kotlin/main.js.kt +++ b/kamel-samples/src/jsMain/kotlin/main.js.kt @@ -1,7 +1,3 @@ -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.window.Window import io.kamel.core.config.KamelConfig import io.kamel.core.config.takeFrom From 8ce5e9acdba40420c8ef9266903f75633ed634f4 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 17:16:56 -0400 Subject: [PATCH 53/74] cleanup --- buildSrc/src/main/kotlin/Dependencies.kt | 8 ++++++-- kamel-image/build.gradle.kts | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 9b9ea741..8f7e812a 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -10,12 +10,10 @@ object Dependencies { const val GradlePlugin = "com.android.tools.build:gradle:${Versions.AGP}" const val Material = "com.google.android.material:material:${Versions.Android.Material}" const val Annotation = "androidx.annotation:annotation:${Versions.Android.Annotation}" - const val UIGraphics = "androidx.compose.ui:ui-graphics:${Versions.Android.UIGraphics}" } object Ktor { const val Core = "io.ktor:ktor-client-core:${Versions.Ktor}" - const val Logging = "io.ktor:ktor-client-logging:${Versions.Ktor}" const val Android = "io.ktor:ktor-client-android:${Versions.Ktor}" const val Darwin = "io.ktor:ktor-client-darwin:${Versions.Ktor}" const val Js = "io.ktor:ktor-client-js:${Versions.Ktor}" @@ -38,6 +36,10 @@ object Dependencies { const val Test = "dev.icerock.moko:resources-test:${Versions.MokoResources}" } + object XmlUtil { + const val Serialization = "io.github.pdvrieze.xmlutil:serialization:${Versions.XmlUtil}" + } + } object Versions { @@ -48,6 +50,8 @@ object Versions { const val Compose = "1.4.0" const val AGP = "7.4.2" const val MokoResources = "0.20.1" + const val XmlUtil = "0.86.0" + object Android { const val ActivityCompose = "1.7.1" diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 1e022d1f..5b658e6a 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -99,7 +99,7 @@ kotlin { val nonJvmMain by creating { dependsOn(commonMain) dependencies { - implementation("io.github.pdvrieze.xmlutil:serialization:0.86.0") + implementation(Dependencies.XmlUtil.Serialization) } } From c0730c59c7d937eb21451bcd1f8afdffe16754d6 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 17:35:11 -0400 Subject: [PATCH 54/74] example of android failing to build with moko-resources 0.22.0 --- buildSrc/src/main/kotlin/Dependencies.kt | 2 +- kotlin-js-store/yarn.lock | 162 ++++++++++++++++------- 2 files changed, 112 insertions(+), 52 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 8f7e812a..ceee7a97 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -49,7 +49,7 @@ object Versions { const val Coroutines = "1.7.0" const val Compose = "1.4.0" const val AGP = "7.4.2" - const val MokoResources = "0.20.1" + const val MokoResources = "0.22.0" const val XmlUtil = "0.86.0" diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index ead26e82..10befde4 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -637,11 +637,6 @@ bcp-47@1.0.8: is-alphanumerical "^1.0.0" is-decimal "^1.0.0" -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -938,6 +933,25 @@ cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +css-loader@6.7.3: + version "6.7.3" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.3.tgz#1e8799f3ccc5874fdd55461af51137fcc5befbcd" + integrity sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.19" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.3.8" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + custom-event@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" @@ -1064,11 +1078,6 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -1272,14 +1281,6 @@ faye-websocket@^0.11.3: dependencies: websocket-driver ">=0.5.1" -file-loader@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" - integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -1570,6 +1571,11 @@ iconv-lite@^0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + import-local@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" @@ -1795,11 +1801,6 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json5@^2.1.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -1877,15 +1878,6 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== -loader-utils@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" - integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -1924,6 +1916,13 @@ log4js@^6.4.1: rfdc "^1.3.0" streamroller "^3.1.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + magic-string@^0.25.7: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -2003,6 +2002,13 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mini-css-extract-plugin@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz#9a1251d15f2035c342d99a468ab9da7a0451b71e" + integrity sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg== + dependencies: + schema-utils "^4.0.0" + minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -2095,6 +2101,11 @@ nanoid@3.3.3: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== +nanoid@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== + negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -2279,6 +2290,56 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" + integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== + +postcss-modules-local-by-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" + integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" + integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: + version "6.0.12" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.12.tgz#2efae5ffab3c8bfb2b7fbf0c426e3bca616c4abb" + integrity sha512-NdxGCAZdRrwVI1sy59+Wzrh+pMMHxapGnpfenDVlMEXoOcvt4pGE0JLK9YY2F5dLxcFYA/YbVQKhcGU+FtSYQg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.4.19: + version "8.4.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.23.tgz#df0aee9ac7c5e53e1075c24a3613496f9e6552ab" + integrity sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -2474,15 +2535,6 @@ safe-identifier@^0.4.1: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -schema-utils@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.2.tgz#36c10abca6f7577aeae136c804b0c741edeadc99" - integrity sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - schema-utils@^3.1.0, schema-utils@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" @@ -2514,6 +2566,13 @@ selfsigned@^2.0.1: dependencies: node-forge "^1" +semver@^7.3.8: + version "7.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.0.tgz#ed8c5dc8efb6c629c88b23d41dc9bf40c1d96cd0" + integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA== + dependencies: + lru-cache "^6.0.0" + send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -2769,6 +2828,11 @@ strip-json-comments@3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +style-loader@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" + integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== + supports-color@8.1.1, supports-color@^8.0.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -2918,16 +2982,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-loader@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" - integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== - dependencies: - loader-utils "^2.0.0" - mime-types "^2.1.27" - schema-utils "^3.0.0" - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -3166,6 +3221,11 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" From 297f75a018021cf8f613e2c36e6f8bbcab610e31 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 17:46:48 -0400 Subject: [PATCH 55/74] remove resourcesFetcher from nonJvm. It's not really applicable --- .../io/kamel/image/config/KamelConfig.kt | 6 ---- .../kamel/image/fetcher/ResourcesFetcher.kt | 35 ------------------- 2 files changed, 41 deletions(-) delete mode 100644 kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/config/KamelConfig.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/config/KamelConfig.kt index edc02f67..f31b3c1f 100644 --- a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/config/KamelConfig.kt +++ b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/config/KamelConfig.kt @@ -3,12 +3,6 @@ package io.kamel.image.config import io.kamel.core.config.KamelConfigBuilder import io.kamel.image.decoder.ImageVectorDecoder import io.kamel.image.decoder.SvgDecoder -import io.kamel.image.fetcher.ResourcesFetcher - -/** - * Adds application resources fetcher to the [KamelConfigBuilder]. - */ -public fun KamelConfigBuilder.resourcesFetcher(): Unit = fetcher(ResourcesFetcher) public fun KamelConfigBuilder.imageVectorDecoder(): Unit = decoder(ImageVectorDecoder) diff --git a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt b/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt deleted file mode 100644 index 47450d2d..00000000 --- a/kamel-image/src/nonJvmMain/kotlin/io/kamel/image/fetcher/ResourcesFetcher.kt +++ /dev/null @@ -1,35 +0,0 @@ -package io.kamel.image.fetcher - -import io.kamel.core.DataSource -import io.kamel.core.Resource -import io.kamel.core.config.ResourceConfig -import io.kamel.core.fetcher.Fetcher -import io.kamel.image.utils.path -import io.ktor.http.* -import io.ktor.utils.io.* -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import kotlin.reflect.KClass - -internal object ResourcesFetcher : Fetcher { - - override val inputDataKClass: KClass = Url::class - - override val source: DataSource = DataSource.Disk - - override val Url.isSupported: Boolean - get() = false//Thread.currentThread().contextClassLoader?.getResource(path) != null - - override fun fetch( - data: Url, - resourceConfig: ResourceConfig - ): Flow> = flow { - TODO() -// val bytes = Thread.currentThread().contextClassLoader -// ?.getResource(data.path) -// ?.readBytes() -// ?.let { ByteReadChannel(it) } ?: error("Unable to find resource $data") -// emit(Resource.Success(bytes, source)) - } - -} \ No newline at end of file From 06adcd2eace4cf4905e04ef4e84dadeb7f39fe1b Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 17:48:10 -0400 Subject: [PATCH 56/74] fix visibility --- kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt b/kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt index fc8cbe52..7204d8d0 100644 --- a/kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt +++ b/kamel-image/src/nonJvmMain/kotlin/loadSvgPainter.kt @@ -32,7 +32,7 @@ import kotlin.math.ceil // Note: copied from here: // https://github.com/JetBrains/compose-multiplatform-core/blob/5c26b7b9f5619ee4f319c6caf43192851b8ee15e/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/res/DesktopSvgResources.desktop.kt#L51 // todo: remove when available in common androidx -fun loadSvgPainter( +internal fun loadSvgPainter( bytes: ByteArray, density: Density ): Painter { From e0c705e0d990ca9681c3ba8fad93d21ba04a2dc2 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 18:00:20 -0400 Subject: [PATCH 57/74] cleanup removed --- kamel-samples/src/jsMain/kotlin/main.js.kt | 1 - kamel-samples/src/macosMain/kotlin/main.macos.kt | 1 - kamel-samples/src/uikitMain/kotlin/main.uikit.kt | 1 - 3 files changed, 3 deletions(-) diff --git a/kamel-samples/src/jsMain/kotlin/main.js.kt b/kamel-samples/src/jsMain/kotlin/main.js.kt index db57cb22..2d79a87e 100644 --- a/kamel-samples/src/jsMain/kotlin/main.js.kt +++ b/kamel-samples/src/jsMain/kotlin/main.js.kt @@ -8,7 +8,6 @@ import org.jetbrains.skiko.wasm.onWasmReady public fun main() { val kamelConfig = KamelConfig { takeFrom(KamelConfig.Default) - resourcesFetcher() imageVectorDecoder() svgDecoder() imageBitmapDecoder() diff --git a/kamel-samples/src/macosMain/kotlin/main.macos.kt b/kamel-samples/src/macosMain/kotlin/main.macos.kt index c528060a..bc6db61e 100644 --- a/kamel-samples/src/macosMain/kotlin/main.macos.kt +++ b/kamel-samples/src/macosMain/kotlin/main.macos.kt @@ -10,7 +10,6 @@ public fun main() { NSApplication.sharedApplication() val kamelConfig = KamelConfig { takeFrom(KamelConfig.Default) - resourcesFetcher() imageVectorDecoder() svgDecoder() imageBitmapDecoder() diff --git a/kamel-samples/src/uikitMain/kotlin/main.uikit.kt b/kamel-samples/src/uikitMain/kotlin/main.uikit.kt index a1dd3e4c..e4d2782c 100644 --- a/kamel-samples/src/uikitMain/kotlin/main.uikit.kt +++ b/kamel-samples/src/uikitMain/kotlin/main.uikit.kt @@ -41,7 +41,6 @@ class SkikoAppDelegate : UIResponder, UIApplicationDelegateProtocol { window = UIWindow(frame = UIScreen.mainScreen.bounds) val kamelConfig = KamelConfig { takeFrom(KamelConfig.Default) - resourcesFetcher() imageVectorDecoder() svgDecoder() imageBitmapDecoder() From f6c37beca108d0f16cd535abc808a9ed7c017756 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 19:31:09 -0400 Subject: [PATCH 58/74] add coroutines workaround for KamelImageTest there's a conflict causing runTest to fail --- buildSrc/src/main/kotlin/Dependencies.kt | 1 + kamel-image/build.gradle.kts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 8f7e812a..7f175e04 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -23,6 +23,7 @@ object Dependencies { object Coroutines { const val Core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.Coroutines}" const val Test = "org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.Coroutines}" + const val Test164 = "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4" } object Testing { diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 5b658e6a..31b7e356 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -60,7 +60,9 @@ kotlin { implementation(project(":kamel-tests")) implementation(kotlin("test")) implementation(Dependencies.Testing.Ktor) - implementation(Dependencies.Coroutines.Test) + // todo: remove this workaround for running compose tests + // when compose updates to coroutines 1.7.0 + implementation(Dependencies.Coroutines.Test164) } } From ce4c236b9caf1db2c18286104eae69e5a47e3dc0 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 19:32:55 -0400 Subject: [PATCH 59/74] cleanup --- build.gradle.kts | 34 ++++++++++++++++++++++++++++++++++ kamel-samples/build.gradle.kts | 5 ----- kamel-tests/build.gradle.kts | 7 +------ 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 36943cb0..985ab4bc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -128,6 +128,40 @@ allprojects { } } + // workaround for: https://github.com/icerockdev/moko-resources/issues/421#issuecomment-1484530912 + // remove after https://github.com/icerockdev/moko-resources/issues/477 resolved and moko-resources can + // be updated + tasks.matching { it.name == "jvmProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRjvmMain" }) + } + tasks.matching { it.name == "desktopProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRdesktopMain" }) + } + tasks.matching { it.name == "iosSimulatorArm64ProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRiosSimulatorArm64Main" }) + } + tasks.matching { it.name == "metadataIosMainProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRcommonMain" }) + } + tasks.matching { it.name == "metadataCommonMainProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRcommonMain" }) + } + tasks.matching { it.name == "iosX64ProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRiosX64Main" }) + } + tasks.matching { it.name == "iosArm64ProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRiosArm64Main" }) + } + tasks.matching { it.name == "macosArm64ProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRmacosArm64Main" }) + } + tasks.matching { it.name == "macosX64ProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRmacosX64Main" }) + } + tasks.matching { it.name == "jsProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRjsMain" }) + } + } nexusStaging { diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index db2bd5b6..a4345c8a 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -217,11 +217,6 @@ tasks.register("desktopCopyResourcesFromKamelTests") { tasks.getByName("desktopProcessResources").dependsOn("desktopCopyResourcesFromKamelTests") tasks.getByName("desktopCopyResourcesFromKamelTests").dependsOn(":kamel-tests:generateMRjvmMain") -tasks.findByName("desktopProcessResources")!!.dependsOn("generateMRcommonMain") -tasks.findByName("desktopProcessResources")!!.dependsOn("generateMRdesktopMain") -tasks.findByName("jsProcessResources")!!.dependsOn("generateMRcommonMain") -tasks.findByName("jsProcessResources")!!.dependsOn("generateMRjsMain") - // todo: Remove when resolved: https://github.com/icerockdev/moko-resources/issues/372 tasks.withType() .matching { linkTask -> linkTask.binary is AbstractExecutable } diff --git a/kamel-tests/build.gradle.kts b/kamel-tests/build.gradle.kts index 22c87434..717eced6 100644 --- a/kamel-tests/build.gradle.kts +++ b/kamel-tests/build.gradle.kts @@ -71,9 +71,4 @@ android { multiplatformResources { multiplatformResourcesPackage = "io.kamel.tests" -} - -tasks.findByName("jvmProcessResources")!!.dependsOn("generateMRcommonMain") -tasks.findByName("jvmProcessResources")!!.dependsOn("generateMRjvmMain") -tasks.findByName("jsProcessResources")!!.dependsOn("generateMRcommonMain") -tasks.findByName("jsProcessResources")!!.dependsOn("generateMRjsMain") \ No newline at end of file +} \ No newline at end of file From 17617e6ed9d74dae7ec856f3f8270e536f2b9a1a Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 19:33:34 -0400 Subject: [PATCH 60/74] fix testFetchingNonEmptyImageBytes for js --- .gitignore | 5 +---- kamel-core/build.gradle.kts | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index bf916a71..3e948b17 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,4 @@ local.properties !/.idea/codeStyles/ # moko-resources-generated -kamel-tests/webpack.config.d/moko-resources-generated.js -kamel-tests/karma.config.d/moko-resources-generated.js -kamel-samples/webpack.config.d/moko-resources-generated.js -kamel-samples/karma.config.d/moko-resources-generated.js +moko-resources-generated.js diff --git a/kamel-core/build.gradle.kts b/kamel-core/build.gradle.kts index 99a65c30..54292a2d 100644 --- a/kamel-core/build.gradle.kts +++ b/kamel-core/build.gradle.kts @@ -2,7 +2,6 @@ import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractExecutable import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBinary -import org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink import org.jetbrains.kotlin.library.impl.KotlinLibraryLayoutImpl import java.io.FileFilter @@ -12,6 +11,7 @@ plugins { compose `maven-publish` signing + mokoResources } kotlin { @@ -62,6 +62,7 @@ kotlin { implementation(compose.runtime) implementation(Dependencies.Coroutines.Core) api(Dependencies.Ktor.Core) + implementation(Dependencies.MokoResources.Core) } } @@ -169,3 +170,17 @@ tasks.withType() } } } + +multiplatformResources { + multiplatformResourcesPackage = "io.kamel.core" +} + +// todo: remove after https://github.com/icerockdev/moko-resources/issues/392 resolved +// copy resources from kamel-tests into the proper directory for kamel-samples so they are packaged for +// the web app +tasks.register("jsCopyResourcesFromKamelTests") { + from("../kamel-tests/build/generated/moko/jsMain/iokameltests/res") + into("build/generated/moko/jsMain/iokamelcore/res") +} +tasks.getByName("jsProcessResources").dependsOn("jsCopyResourcesFromKamelTests") +tasks.getByName("jsCopyResourcesFromKamelTests").dependsOn(":kamel-tests:generateMRjsMain") From 9f43437a3ebba6c012b567dfd11d6d87334c431f Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 19:35:44 -0400 Subject: [PATCH 61/74] cleanup --- kamel-core/build.gradle.kts | 2 +- kamel-samples/build.gradle.kts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kamel-core/build.gradle.kts b/kamel-core/build.gradle.kts index 54292a2d..162aadf8 100644 --- a/kamel-core/build.gradle.kts +++ b/kamel-core/build.gradle.kts @@ -181,6 +181,6 @@ multiplatformResources { tasks.register("jsCopyResourcesFromKamelTests") { from("../kamel-tests/build/generated/moko/jsMain/iokameltests/res") into("build/generated/moko/jsMain/iokamelcore/res") + dependsOn(":kamel-tests:generateMRjsMain") } tasks.getByName("jsProcessResources").dependsOn("jsCopyResourcesFromKamelTests") -tasks.getByName("jsCopyResourcesFromKamelTests").dependsOn(":kamel-tests:generateMRjsMain") diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index a4345c8a..9a7fd2a4 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -206,16 +206,16 @@ project.tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile::class.ja tasks.register("jsCopyResourcesFromKamelTests") { from("../kamel-tests/build/generated/moko/jsMain/iokameltests/res") into("build/generated/moko/jsMain/iokamelsamples/res") + dependsOn(":kamel-tests:generateMRjsMain") } tasks.getByName("jsProcessResources").dependsOn("jsCopyResourcesFromKamelTests") -tasks.getByName("jsCopyResourcesFromKamelTests").dependsOn(":kamel-tests:generateMRjsMain") tasks.register("desktopCopyResourcesFromKamelTests") { from("../kamel-tests/build/generated/moko/jvmMain/iokameltests/res") into("build/generated/moko/desktopMain/iokamelsamples/res") + dependsOn(":kamel-tests:generateMRjvmMain") } tasks.getByName("desktopProcessResources").dependsOn("desktopCopyResourcesFromKamelTests") -tasks.getByName("desktopCopyResourcesFromKamelTests").dependsOn(":kamel-tests:generateMRjvmMain") // todo: Remove when resolved: https://github.com/icerockdev/moko-resources/issues/372 tasks.withType() From 9eed5c2df28b39aabbc19c3649e730462dbf286f Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 19:42:20 -0400 Subject: [PATCH 62/74] remove workaround (not working) downgrade to coroutines 1.6.4 now all tests are passing --- buildSrc/src/main/kotlin/Dependencies.kt | 4 +--- .../src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt | 3 +-- kamel-image/build.gradle.kts | 4 +--- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 7f175e04..6ac325e8 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -23,7 +23,6 @@ object Dependencies { object Coroutines { const val Core = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.Coroutines}" const val Test = "org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.Coroutines}" - const val Test164 = "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4" } object Testing { @@ -47,7 +46,7 @@ object Versions { const val Kotlin = "1.8.20" const val Ktor = "2.3.0" - const val Coroutines = "1.7.0" + const val Coroutines = "1.6.4" const val Compose = "1.4.0" const val AGP = "7.4.2" const val MokoResources = "0.20.1" @@ -59,7 +58,6 @@ object Versions { const val Appcompat = "1.6.1" const val Material = "1.8.0" const val Annotation = "1.6.0" - const val UIGraphics = "1.4.3" } } \ No newline at end of file diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt index f24958f9..139a413d 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt @@ -4,7 +4,6 @@ import kotlinx.cinterop.addressOf import kotlinx.cinterop.usePinned import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.IO import platform.Foundation.NSData import platform.Foundation.NSFileHandle import platform.Foundation.NSURL @@ -12,7 +11,7 @@ import platform.Foundation.fileHandleForReadingAtPath import platform.posix.memcpy -internal actual val Dispatchers.kamel: CoroutineDispatcher get() = IO +internal actual val Dispatchers.kamel: CoroutineDispatcher get() = Default public actual class File(public val path: String) { diff --git a/kamel-image/build.gradle.kts b/kamel-image/build.gradle.kts index 31b7e356..5b658e6a 100644 --- a/kamel-image/build.gradle.kts +++ b/kamel-image/build.gradle.kts @@ -60,9 +60,7 @@ kotlin { implementation(project(":kamel-tests")) implementation(kotlin("test")) implementation(Dependencies.Testing.Ktor) - // todo: remove this workaround for running compose tests - // when compose updates to coroutines 1.7.0 - implementation(Dependencies.Coroutines.Test164) + implementation(Dependencies.Coroutines.Test) } } From a0005cb66a9ef38008122a5122e448a17f583632 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 19:49:49 -0400 Subject: [PATCH 63/74] more moko-resources gradle task dependency fixes --- build.gradle.kts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 985ab4bc..d5ae8825 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -152,6 +152,12 @@ allprojects { tasks.matching { it.name == "iosArm64ProcessResources" }.configureEach { dependsOn(tasks.matching { it.name == "generateMRiosArm64Main" }) } + tasks.matching { it.name == "uikitSimulatorArm64ProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRuikitSimulatorArm64Main" }) + } + tasks.matching { it.name == "uikitX64ProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRuikitX64Main" }) + } tasks.matching { it.name == "macosArm64ProcessResources" }.configureEach { dependsOn(tasks.matching { it.name == "generateMRmacosArm64Main" }) } From 220a539c71956b3860e3a5df59600455c293a5fd Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 19:52:33 -0400 Subject: [PATCH 64/74] fix warnings --- .../src/uikitMain/kotlin/main.uikit.kt | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/kamel-samples/src/uikitMain/kotlin/main.uikit.kt b/kamel-samples/src/uikitMain/kotlin/main.uikit.kt index e4d2782c..52a9341b 100644 --- a/kamel-samples/src/uikitMain/kotlin/main.uikit.kt +++ b/kamel-samples/src/uikitMain/kotlin/main.uikit.kt @@ -1,11 +1,14 @@ -import androidx.compose.ui.window.Application import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding -import androidx.compose.ui.unit.dp import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.ComposeUIViewController import io.kamel.core.config.KamelConfig import io.kamel.core.config.takeFrom -import io.kamel.image.config.* +import io.kamel.image.config.Default +import io.kamel.image.config.imageBitmapDecoder +import io.kamel.image.config.imageVectorDecoder +import io.kamel.image.config.svgDecoder import io.kamel.samples.launcher import kotlinx.cinterop.autoreleasepool import kotlinx.cinterop.cstr @@ -25,14 +28,14 @@ fun main() { } } -class SkikoAppDelegate : UIResponder, UIApplicationDelegateProtocol { - companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta +internal class SkikoAppDelegate : UIResponder, UIApplicationDelegateProtocol { + internal companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta @OverrideInit - constructor() : super() + internal constructor() : super() private var _window: UIWindow? = null - override fun window() = _window + override fun window(): UIWindow? = _window override fun setWindow(window: UIWindow?) { _window = window } @@ -45,7 +48,7 @@ class SkikoAppDelegate : UIResponder, UIApplicationDelegateProtocol { svgDecoder() imageBitmapDecoder() } - window!!.rootViewController = Application("Sample") { + window!!.rootViewController = ComposeUIViewController { Column(Modifier.padding(top = 30.dp)) { launcher(kamelConfig) } From 8f4b04775853c462695c8824287938efce3a4be1 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 20:20:02 -0400 Subject: [PATCH 65/74] another moko-resources gradle task dependency fix --- build.gradle.kts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index d5ae8825..2f88c95d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -143,6 +143,9 @@ allprojects { tasks.matching { it.name == "metadataIosMainProcessResources" }.configureEach { dependsOn(tasks.matching { it.name == "generateMRcommonMain" }) } + tasks.matching { it.name == "metadataDarwinMainProcessResources" }.configureEach { + dependsOn(tasks.matching { it.name == "generateMRcommonMain" }) + } tasks.matching { it.name == "metadataCommonMainProcessResources" }.configureEach { dependsOn(tasks.matching { it.name == "generateMRcommonMain" }) } From 0ffd67b78cac68cbebbd9a1f9c99b780d2309baa Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 20:20:11 -0400 Subject: [PATCH 66/74] warning fix --- kamel-samples/src/uikitMain/kotlin/main.uikit.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kamel-samples/src/uikitMain/kotlin/main.uikit.kt b/kamel-samples/src/uikitMain/kotlin/main.uikit.kt index 52a9341b..8fdc59f9 100644 --- a/kamel-samples/src/uikitMain/kotlin/main.uikit.kt +++ b/kamel-samples/src/uikitMain/kotlin/main.uikit.kt @@ -17,7 +17,7 @@ import kotlinx.cinterop.toCValues import platform.Foundation.NSStringFromClass import platform.UIKit.* -fun main() { +public fun main() { val args = emptyArray() memScoped { val argc = args.size + 1 From 2aeeb1e99249707619faa96608dde51f6d550ae2 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 21:25:24 -0400 Subject: [PATCH 67/74] Don't apply mokoResources to kamel-core --- .gitignore | 2 ++ gradle/pack-core-tests-resources.gradle.kts | 36 +++++++++++++++++++++ kamel-core/build.gradle.kts | 7 ++-- 3 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 gradle/pack-core-tests-resources.gradle.kts diff --git a/.gitignore b/.gitignore index 3e948b17..5a0eff78 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ local.properties # moko-resources-generated moko-resources-generated.js +# generated +pack-test-resources-generated.js \ No newline at end of file diff --git a/gradle/pack-core-tests-resources.gradle.kts b/gradle/pack-core-tests-resources.gradle.kts new file mode 100644 index 00000000..e3ab88bf --- /dev/null +++ b/gradle/pack-core-tests-resources.gradle.kts @@ -0,0 +1,36 @@ +/*** + * How to handle Web Workers "standard" syntax with webpack: + * https://stackoverflow.com/a/41630622/1363742 + */ +fun createWebpackConfig(){ + val rootProjectAbsPath = rootProject.projectDir.absolutePath + val path = """"$rootProjectAbsPath/kamel-core/build/generated/moko/jsMain/iokamelcore/res"""" + val webpackConfig = File(projectDir, "webpack.config.d/pack-test-resources-generated.js") + val configText = + """const path = require('path'); + +const mokoResourcePath = path.resolve($path); + +config.module.rules.push( + { + test: /\.(.*)/, + include: [ + path.resolve(mokoResourcePath) + ], + type: 'asset/resource' + } +); + +config.resolve.modules.push( + path.resolve(mokoResourcePath) +);""" + webpackConfig.writeText(configText) +} + +tasks.create("createPackResourcesWebpackConfig") { + doFirst { + createWebpackConfig() + } +} + +tasks.getByName("jsJar").dependsOn("createPackResourcesWebpackConfig") diff --git a/kamel-core/build.gradle.kts b/kamel-core/build.gradle.kts index 162aadf8..c14b4b5f 100644 --- a/kamel-core/build.gradle.kts +++ b/kamel-core/build.gradle.kts @@ -11,7 +11,6 @@ plugins { compose `maven-publish` signing - mokoResources } kotlin { @@ -62,7 +61,6 @@ kotlin { implementation(compose.runtime) implementation(Dependencies.Coroutines.Core) api(Dependencies.Ktor.Core) - implementation(Dependencies.MokoResources.Core) } } @@ -171,9 +169,6 @@ tasks.withType() } } -multiplatformResources { - multiplatformResourcesPackage = "io.kamel.core" -} // todo: remove after https://github.com/icerockdev/moko-resources/issues/392 resolved // copy resources from kamel-tests into the proper directory for kamel-samples so they are packaged for @@ -184,3 +179,5 @@ tasks.register("jsCopyResourcesFromKamelTests") { dependsOn(":kamel-tests:generateMRjsMain") } tasks.getByName("jsProcessResources").dependsOn("jsCopyResourcesFromKamelTests") + +apply(from = "$rootDir/gradle/pack-core-tests-resources.gradle.kts") \ No newline at end of file From 1cb670cd7537aa63496fcc0877555b20d4c83e0c Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Sun, 7 May 2023 22:05:15 -0400 Subject: [PATCH 68/74] Dispatchers.kamel -> Dispatchers.Kamel --- .../kotlin/io/kamel/core/config/ResourceConfigBuilder.kt | 4 ++-- .../src/commonMain/kotlin/io/kamel/core/utils/Platform.kt | 2 +- .../src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt | 2 +- kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt | 2 +- .../src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/config/ResourceConfigBuilder.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/config/ResourceConfigBuilder.kt index 71c25f7a..64d1b986 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/config/ResourceConfigBuilder.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/config/ResourceConfigBuilder.kt @@ -1,7 +1,7 @@ package io.kamel.core.config import androidx.compose.ui.unit.Density -import io.kamel.core.utils.kamel +import io.kamel.core.utils.Kamel import io.kamel.core.utils.supervisorJob import io.ktor.client.request.* import kotlinx.coroutines.Dispatchers @@ -19,7 +19,7 @@ public class ResourceConfigBuilder { * CoroutineContext used while loading the resource. * @see ResourceConfig.coroutineContext */ - public var coroutineContext: CoroutineContext = supervisorJob.plus(Dispatchers.kamel) + public var coroutineContext: CoroutineContext = supervisorJob.plus(Dispatchers.Kamel) /** * Screen density. diff --git a/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/Platform.kt index 8f9a62a3..23bc72e3 100644 --- a/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/commonMain/kotlin/io/kamel/core/utils/Platform.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.SupervisorJob internal val supervisorJob = SupervisorJob() -internal expect val Dispatchers.kamel: CoroutineDispatcher +internal expect val Dispatchers.Kamel: CoroutineDispatcher public expect class File diff --git a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt index 139a413d..a5565229 100644 --- a/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/darwinMain/kotlin/io/kamel/core/utils/Platform.kt @@ -11,7 +11,7 @@ import platform.Foundation.fileHandleForReadingAtPath import platform.posix.memcpy -internal actual val Dispatchers.kamel: CoroutineDispatcher get() = Default +internal actual val Dispatchers.Kamel: CoroutineDispatcher get() = Default public actual class File(public val path: String) { diff --git a/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt b/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt index c53e1238..7f094885 100644 --- a/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt +++ b/kamel-core/src/jsMain/kotlin/io/kamel/core/utils/Platform.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers -internal actual val Dispatchers.kamel: CoroutineDispatcher get() = Default +internal actual val Dispatchers.Kamel: CoroutineDispatcher get() = Default public actual class File(public val file: org.w3c.files.File) { override fun toString(): String { diff --git a/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt b/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt index e95c1ded..29cde4b9 100644 --- a/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt +++ b/kamel-core/src/jvmMain/kotlin/io/kamel/core/utils/JvmPlatform.kt @@ -5,7 +5,7 @@ import kotlinx.coroutines.Dispatchers import java.net.URI import java.net.URL -internal actual val Dispatchers.kamel: CoroutineDispatcher get() = IO +internal actual val Dispatchers.Kamel: CoroutineDispatcher get() = IO public actual typealias File = java.io.File From ebaac383578ce263db6742b622729c7beeab2414 Mon Sep 17 00:00:00 2001 From: Aleksey Mikhailov Date: Mon, 8 May 2023 20:29:34 +0600 Subject: [PATCH 69/74] fix actual declaration not found in generated dir --- kamel-samples/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kamel-samples/build.gradle.kts b/kamel-samples/build.gradle.kts index db2bd5b6..0cd64c1d 100644 --- a/kamel-samples/build.gradle.kts +++ b/kamel-samples/build.gradle.kts @@ -12,8 +12,8 @@ import org.jetbrains.kotlin.konan.file.File as KonanFile plugins { multiplatform compose - mokoResources `android-application` + mokoResources } android { From bccbe5f10afdf72fa0aacb36c28e7f6f3b194011 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Mon, 8 May 2023 12:01:06 -0400 Subject: [PATCH 70/74] remove moko-resources task dependency workaround --- build.gradle.kts | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2f88c95d..36943cb0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -128,49 +128,6 @@ allprojects { } } - // workaround for: https://github.com/icerockdev/moko-resources/issues/421#issuecomment-1484530912 - // remove after https://github.com/icerockdev/moko-resources/issues/477 resolved and moko-resources can - // be updated - tasks.matching { it.name == "jvmProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRjvmMain" }) - } - tasks.matching { it.name == "desktopProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRdesktopMain" }) - } - tasks.matching { it.name == "iosSimulatorArm64ProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRiosSimulatorArm64Main" }) - } - tasks.matching { it.name == "metadataIosMainProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRcommonMain" }) - } - tasks.matching { it.name == "metadataDarwinMainProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRcommonMain" }) - } - tasks.matching { it.name == "metadataCommonMainProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRcommonMain" }) - } - tasks.matching { it.name == "iosX64ProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRiosX64Main" }) - } - tasks.matching { it.name == "iosArm64ProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRiosArm64Main" }) - } - tasks.matching { it.name == "uikitSimulatorArm64ProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRuikitSimulatorArm64Main" }) - } - tasks.matching { it.name == "uikitX64ProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRuikitX64Main" }) - } - tasks.matching { it.name == "macosArm64ProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRmacosArm64Main" }) - } - tasks.matching { it.name == "macosX64ProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRmacosX64Main" }) - } - tasks.matching { it.name == "jsProcessResources" }.configureEach { - dependsOn(tasks.matching { it.name == "generateMRjsMain" }) - } - } nexusStaging { From 1fee4d48674ecf95c1d9e0dd6f5e30a1c3d32c8b Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Fri, 19 May 2023 14:22:31 -0400 Subject: [PATCH 71/74] update publishing info --- build.gradle.kts | 4 ++-- buildSrc/src/main/kotlin/Kamel.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 36943cb0..2c707198 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -104,8 +104,8 @@ allprojects { name = "MavenCentral" - val releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" - val snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/" + val releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" + val snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/" url = if (version.toString().endsWith("SNAPSHOT")) uri(snapshotsRepoUrl) else uri(releasesRepoUrl) diff --git a/buildSrc/src/main/kotlin/Kamel.kt b/buildSrc/src/main/kotlin/Kamel.kt index 3b3693d1..5ddd45ea 100644 --- a/buildSrc/src/main/kotlin/Kamel.kt +++ b/buildSrc/src/main/kotlin/Kamel.kt @@ -1,4 +1,4 @@ object Kamel { - const val Group = "com.alialbaali.kamel" - const val Version = "0.4.1" + const val Group = "media.kamel" + const val Version = "0.5.0-SNAPSHOT" } \ No newline at end of file From 9f8a514adf408c75d466e668cc5dbe29662d414c Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 24 May 2023 15:35:35 -0400 Subject: [PATCH 72/74] update readme --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8b39c06b..a5de730a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Kotlin](https://img.shields.io/badge/kotlin-v1.7.0-blue.svg?logo=kotlin)](http://kotlinlang.org) [![Compose](https://img.shields.io/badge/compose-v1.2.0-alpha2?logo=compose&color=blue)](http://kotlinlang.org) -Kamel is an asynchronous media loading library for Compose. It provides a simple, customizable and +Kamel is an asynchronous media loading library for [Compose Multiplatform](https://github.com/JetBrains/compose-multiplatform). It provides a simple, customizable and efficient way to load, cache, decode and display images in your application. By default, it uses Ktor client for loading resources. @@ -90,9 +90,12 @@ lazyPainterResource(data = Url("https://www.example.com/image.jpg")) // URI lazyPainterResource(data = URI("https://www.example.com/image.png")) -// File +// File (JVM, Native) lazyPainterResource(data = File("/path/to/image.png")) +// File (JS) +lazyPainterResource(data = File(org.w3c.files.File(arrayOf(blob), "/path/to/image.png"))) + // URL lazyPainterResource(data = URL("https://www.example.com/image.jpg")) From 3563f384a97690cd8ed51df3f46f1a33729da696 Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 24 May 2023 16:11:56 -0400 Subject: [PATCH 73/74] fix readme dependency --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a5de730a..ad7eb8d6 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ kotlin { sourceSets { commonMain { dependencies { - implementation("com.alialbaali.kamel:kamel-image:0.4.0") + implementation("media.kamel:kamel-image:0.4.0") // ... } } @@ -63,7 +63,7 @@ Add the dependency to the dependencies block: ```kotlin dependencies { - implementation("com.alialbaali.kamel:kamel-image:0.4.0") + implementation("media.kamel:kamel-image:0.4.0") // ... } ``` From 398e9bf3a96ac67f8f2fc107931d9e295ce2d96c Mon Sep 17 00:00:00 2001 From: Luca Spinazzola Date: Wed, 24 May 2023 16:29:52 -0400 Subject: [PATCH 74/74] fix badges. v0.5.0 --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ad7eb8d6..67bf7c7c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # Kamel -[![Version](https://img.shields.io/maven-central/v/com.alialbaali.kamel/kamel-core?label=version&color=blue)](https://search.maven.org/search?q=com.alialbaali.kamel) -[![Snapshot](https://img.shields.io/nexus/s/com.alialbaali.kamel/kamel-core?label=snapshot&server=https%3A%2F%2Foss.sonatype.org)](https://oss.sonatype.org/content/repositories/snapshots/com/alialbaali/kamel/) +[![Version](https://img.shields.io/maven-central/v/media.kamel/kamel-core?label=version&color=blue)](https://search.maven.org/search?q=media.kamel) +[![Snapshot](https://img.shields.io/nexus/s/media.kamel/kamel-core?label=snapshot&server=https%3A%2F%2Fs01.oss.sonatype.org)](https://s01.oss.sonatype.org/content/repositories/snapshots/media/kamel/) [![License](https://img.shields.io/github/license/alialbaali/kamel)](http://www.apache.org/licenses/LICENSE-2.0) -[![Kotlin](https://img.shields.io/badge/kotlin-v1.7.0-blue.svg?logo=kotlin)](http://kotlinlang.org) -[![Compose](https://img.shields.io/badge/compose-v1.2.0-alpha2?logo=compose&color=blue)](http://kotlinlang.org) +[![Kotlin](https://img.shields.io/badge/kotlin-v1.8.20-blue.svg?logo=kotlin)](http://kotlinlang.org) +[![Compose Multiplatform](https://img.shields.io/badge/Compose%20Multiplatform-v1.4.0-blue)](https://github.com/JetBrains/compose-multiplatform) Kamel is an asynchronous media loading library for [Compose Multiplatform](https://github.com/JetBrains/compose-multiplatform). It provides a simple, customizable and efficient way to load, cache, decode and display images in your application. By default, it uses @@ -49,7 +49,7 @@ kotlin { sourceSets { commonMain { dependencies { - implementation("media.kamel:kamel-image:0.4.0") + implementation("media.kamel:kamel-image:0.5.0") // ... } } @@ -63,7 +63,7 @@ Add the dependency to the dependencies block: ```kotlin dependencies { - implementation("media.kamel:kamel-image:0.4.0") + implementation("media.kamel:kamel-image:0.5.0") // ... } ```