diff --git a/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt b/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt index 04272a75633..a1909c90164 100644 --- a/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt +++ b/core/src/commonMain/kotlin/builder/kord/KordBuilder.kt @@ -15,6 +15,7 @@ import dev.kord.core.gateway.DefaultMasterGateway import dev.kord.core.gateway.handler.DefaultGatewayEventInterceptor import dev.kord.core.gateway.handler.GatewayEventInterceptor import dev.kord.core.supplier.EntitySupplyStrategy +import dev.kord.gateway.Compression import dev.kord.gateway.DefaultGateway import dev.kord.gateway.Gateway import dev.kord.gateway.builder.Shards @@ -49,6 +50,7 @@ public abstract class BaseKordBuilder internal constructor(public val token: Str DefaultGateway { client = resources.httpClient identifyRateLimiter = rateLimiter + compression = this@BaseKordBuilder.compression } } } @@ -57,6 +59,11 @@ public abstract class BaseKordBuilder internal constructor(public val token: Str { KtorRequestHandler(it.httpClient, ExclusionRequestRateLimiter(), token = token) } private var cacheBuilder: KordCacheBuilder.(resources: ClientResources) -> Unit = {} + /** + * The [compression mode][Compression] used. + */ + public var compression: Compression = Compression.ZLib + /** * Enables stack trace recovery on the currently defined [RequestHandler]. * diff --git a/gateway/build.gradle.kts b/gateway/build.gradle.kts index 2b646a41100..c27010edd18 100644 --- a/gateway/build.gradle.kts +++ b/gateway/build.gradle.kts @@ -19,12 +19,14 @@ kotlin { jvmMain { dependencies { implementation(libs.slf4j.api) + implementation(libs.zstd.jni) } } jsMain { dependencies { implementation(libs.kotlin.node) implementation(npm("fast-zlib", libs.versions.fastZlib.get())) + implementation(npm("simple-zstd", "1.4.2")) // workaround for https://youtrack.jetbrains.com/issue/KT-43500 / // https://youtrack.jetbrains.com/issue/KT-64109#focus=Comments-27-10064206.0-0 / diff --git a/gateway/src/commonMain/kotlin/Compression.kt b/gateway/src/commonMain/kotlin/Compression.kt new file mode 100644 index 00000000000..598637c4c6f --- /dev/null +++ b/gateway/src/commonMain/kotlin/Compression.kt @@ -0,0 +1,54 @@ +@file:Suppress("FunctionName") + +package dev.kord.gateway + +import dev.kord.common.annotation.KordInternal +import io.ktor.websocket.* + +/** @suppress */ +@KordInternal // Only public for interface, binary API might change at any time +public interface Decompressor : AutoCloseable { + public fun Frame.decompress(): String + + public companion object Noop : Decompressor { + override fun Frame.decompress(): String = data.decodeToString() + override fun close() {} + } +} + +internal expect fun ZLibDecompressor(): Decompressor +internal expect fun ZstdDecompressor(): Decompressor + +/** + * Different compression modes for the Discord gateway. + * + * @property name the name used by the Discord API + */ +public sealed interface Compression { + public val name: String? + public fun newDecompressor(): Decompressor + + /** + * Implementation using no compression. + */ + public data object None : Compression { + override val name: String? = null + override fun newDecompressor(): Decompressor = Decompressor.Noop + } + + /** + * Implementation using [zlib](https://zlib.net/). + */ + public data object ZLib : Compression { + override val name: String = "zlib-stream" + override fun newDecompressor(): Decompressor = ZLibDecompressor() + } + + /** + * Implementation using [Zstandard](https://facebook.github.io/zstd/) + */ + public data object Zstd : Compression { + override val name: String = "zstd-stream" + override fun newDecompressor(): Decompressor = ZstdDecompressor() + } +} diff --git a/gateway/src/commonMain/kotlin/DefaultGateway.kt b/gateway/src/commonMain/kotlin/DefaultGateway.kt index 8a5f673ffc0..5847a68a4f9 100644 --- a/gateway/src/commonMain/kotlin/DefaultGateway.kt +++ b/gateway/src/commonMain/kotlin/DefaultGateway.kt @@ -39,12 +39,13 @@ private sealed class State(val retry: Boolean) { } /** - * @param url The url to connect to. - * @param client The [HttpClient] from which a WebSocket will be created, requires the [WebSockets] plugin to be + * @property url The url to connect to. + * @property client The [HttpClient] from which a WebSocket will be created, requires the [WebSockets] plugin to be * installed. - * @param reconnectRetry A [Retry] used for reconnection attempts. - * @param sendRateLimiter A [RateLimiter] that follows the Discord API specifications for sending messages. - * @param identifyRateLimiter An [IdentifyRateLimiter] that follows the Discord API specifications for identifying. + * @property reconnectRetry A [Retry] used for reconnection attempts. + * @property sendRateLimiter A [RateLimiter] that follows the Discord API specifications for sending messages. + * @property identifyRateLimiter An [IdentifyRateLimiter] that follows the Discord API specifications for identifying. + * @property compression the [compression mode][Compression] used */ public data class DefaultGatewayData( val url: String, @@ -54,6 +55,7 @@ public data class DefaultGatewayData( val identifyRateLimiter: IdentifyRateLimiter, val dispatcher: CoroutineDispatcher, val eventFlow: MutableSharedFlow, + val compression: Compression, ) /** @@ -63,8 +65,6 @@ public class DefaultGateway(private val data: DefaultGatewayData) : Gateway { override val coroutineContext: CoroutineContext = SupervisorJob() + data.dispatcher - private val compression: Boolean - private val _ping = MutableStateFlow(null) override val ping: StateFlow get() = _ping @@ -76,7 +76,7 @@ public class DefaultGateway(private val data: DefaultGatewayData) : Gateway { private val handshakeHandler: HandshakeHandler - private lateinit var inflater: Inflater + private lateinit var decompressor: Decompressor private val jsonParser = Json { ignoreUnknownKeys = true @@ -86,9 +86,10 @@ public class DefaultGateway(private val data: DefaultGatewayData) : Gateway { private val stateMutex = Mutex() init { - val initialUrl = Url(data.url) - compression = initialUrl.parameters.contains("compress", "zlib-stream") - + val initialUrl = URLBuilder(data.url).apply { + val compressionName = data.compression.name ?: return@apply + parameters.append("compress", compressionName) + }.build() val sequence = Sequence() SequenceHandler(events, sequence) handshakeHandler = HandshakeHandler(events, initialUrl, ::trySend, sequence, data.reconnectRetry) @@ -117,7 +118,11 @@ public class DefaultGateway(private val data: DefaultGatewayData) : Gateway { * * > Every connection to the gateway should use its own unique zlib context. */ - inflater = Inflater() + try { + decompressor = data.compression.newDecompressor() + } catch (e: Throwable) { + e.printStackTrace() + } } catch (exception: Exception) { defaultGatewayLogger.error(exception) { "" } if (exception.isTimeout()) { @@ -179,10 +184,7 @@ public class DefaultGateway(private val data: DefaultGatewayData) : Gateway { private suspend fun read(frame: Frame) { defaultGatewayLogger.trace { "Received raw frame: $frame" } - val json = when { - compression -> with(inflater) { frame.inflateData() } - else -> frame.data.decodeToString() - } + val json = with(decompressor) { frame.decompress() } try { defaultGatewayLogger.trace { "Gateway <<< $json" } @@ -195,7 +197,7 @@ public class DefaultGateway(private val data: DefaultGatewayData) : Gateway { } private suspend fun handleClose() { - inflater.close() + decompressor.close() val reason = withTimeoutOrNull(1500) { socket.closeReason.await() @@ -211,6 +213,7 @@ public class DefaultGateway(private val data: DefaultGatewayData) : Gateway { state.update { State.Stopped } throw IllegalStateException("Gateway closed: ${reason.code} ${reason.message}") } + discordReason.resetSession -> { setStopped() } diff --git a/gateway/src/commonMain/kotlin/DefaultGatewayBuilder.kt b/gateway/src/commonMain/kotlin/DefaultGatewayBuilder.kt index 7dd8febc9cc..cf840cb4ddb 100644 --- a/gateway/src/commonMain/kotlin/DefaultGatewayBuilder.kt +++ b/gateway/src/commonMain/kotlin/DefaultGatewayBuilder.kt @@ -18,13 +18,14 @@ import kotlin.time.Duration.Companion.seconds public class DefaultGatewayBuilder { public var url: String = - "wss://gateway.discord.gg/?v=${KordConfiguration.GATEWAY_VERSION}&encoding=json&compress=zlib-stream" + "wss://gateway.discord.gg/?v=${KordConfiguration.GATEWAY_VERSION}&encoding=json" public var client: HttpClient? = null public var reconnectRetry: Retry? = null public var sendRateLimiter: RateLimiter? = null public var identifyRateLimiter: IdentifyRateLimiter? = null public var dispatcher: CoroutineDispatcher = Dispatchers.Default public var eventFlow: MutableSharedFlow = MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE) + public var compression: Compression = Compression.ZLib public fun build(): DefaultGateway { val client = client ?: HttpClient(httpEngine()) { @@ -44,7 +45,8 @@ public class DefaultGatewayBuilder { sendRateLimiter, identifyRateLimiter, dispatcher, - eventFlow + eventFlow, + compression ) return DefaultGateway(data) diff --git a/gateway/src/commonMain/kotlin/Inflater.kt b/gateway/src/commonMain/kotlin/Inflater.kt deleted file mode 100644 index d8078372c4c..00000000000 --- a/gateway/src/commonMain/kotlin/Inflater.kt +++ /dev/null @@ -1,9 +0,0 @@ -package dev.kord.gateway - -import io.ktor.websocket.* - -internal interface Inflater : AutoCloseable { - fun Frame.inflateData(): String -} - -internal expect fun Inflater(): Inflater diff --git a/gateway/src/jsMain/kotlin/Inflater.kt b/gateway/src/jsMain/kotlin/ZLibDecompressor.kt similarity index 76% rename from gateway/src/jsMain/kotlin/Inflater.kt rename to gateway/src/jsMain/kotlin/ZLibDecompressor.kt index 418c269d094..28dd1a67017 100644 --- a/gateway/src/jsMain/kotlin/Inflater.kt +++ b/gateway/src/jsMain/kotlin/ZLibDecompressor.kt @@ -5,10 +5,10 @@ import io.ktor.websocket.* import node.buffer.Buffer import node.buffer.BufferEncoding -internal actual fun Inflater() = object : Inflater { +internal actual fun ZLibDecompressor() = object : Decompressor { private val inflate = Inflate() - override fun Frame.inflateData(): String { + override fun Frame.decompress(): String { val buffer = Buffer.from(data) return inflate.process(buffer).toString(BufferEncoding.utf8) diff --git a/gateway/src/jsMain/kotlin/ZstdDecompressor.kt b/gateway/src/jsMain/kotlin/ZstdDecompressor.kt new file mode 100644 index 00000000000..fe36455df64 --- /dev/null +++ b/gateway/src/jsMain/kotlin/ZstdDecompressor.kt @@ -0,0 +1,29 @@ +package dev.kord.gateway + +import dev.kord.gateway.internal.ZSTDDecompress +import io.ktor.websocket.* +import js.typedarrays.toUint8Array +import node.stream.DuplexEvent +import web.encoding.TextDecoder + +internal actual fun ZstdDecompressor() = object : Decompressor { + private val stream = ZSTDDecompress() + private val decoder = TextDecoder() + + override fun Frame.decompress(): String { + try { + stream.write(data.toUint8Array()) + stream.on(DuplexEvent.FINISH) { + println("finish") + } + stream.on(DuplexEvent.DATA) { + println("Data: $it") + } + } catch (exception: Exception) { + exception.printStackTrace() + } + return "" + } + + override fun close() = stream.end() +} diff --git a/gateway/src/jsMain/kotlin/internal/JsZstd.kt b/gateway/src/jsMain/kotlin/internal/JsZstd.kt new file mode 100644 index 00000000000..e9bc8bdef87 --- /dev/null +++ b/gateway/src/jsMain/kotlin/internal/JsZstd.kt @@ -0,0 +1,7 @@ +@file:JsModule("simple-zstd") + +package dev.kord.gateway.internal + +import node.stream.Transform + +internal external class ZSTDDecompress : Transform diff --git a/gateway/src/jvmMain/kotlin/Inflater.kt b/gateway/src/jvmMain/kotlin/ZLibDecompressor.kt similarity index 80% rename from gateway/src/jvmMain/kotlin/Inflater.kt rename to gateway/src/jvmMain/kotlin/ZLibDecompressor.kt index 348ba9ae389..14aba474830 100644 --- a/gateway/src/jvmMain/kotlin/Inflater.kt +++ b/gateway/src/jvmMain/kotlin/ZLibDecompressor.kt @@ -4,10 +4,10 @@ import io.ktor.websocket.* import java.io.ByteArrayOutputStream import java.util.zip.InflaterOutputStream -internal actual fun Inflater() = object : Inflater { +internal actual fun ZLibDecompressor() = object : Decompressor { private val delegate = java.util.zip.Inflater() - override fun Frame.inflateData(): String { + override fun Frame.decompress(): String { val outputStream = ByteArrayOutputStream() InflaterOutputStream(outputStream, delegate).use { it.write(data) diff --git a/gateway/src/jvmMain/kotlin/ZstdDecompressor.kt b/gateway/src/jvmMain/kotlin/ZstdDecompressor.kt new file mode 100644 index 00000000000..49d45b281cd --- /dev/null +++ b/gateway/src/jvmMain/kotlin/ZstdDecompressor.kt @@ -0,0 +1,33 @@ +package dev.kord.gateway + +import com.github.luben.zstd.ZstdInputStream +import io.ktor.websocket.* +import java.io.ByteArrayInputStream +import java.io.InputStream + +internal actual fun ZstdDecompressor() = object : Decompressor { + + private val input = UpdatableByteArrayInputStream() + private val zstdStream = ZstdInputStream(input).apply { continuous = true } + + override fun Frame.decompress(): String { + input.updateDelegate(data) + return zstdStream.readAllBytes().decodeToString() + } + + override fun close() { + zstdStream.close() + } +} + +private class UpdatableByteArrayInputStream : InputStream() { + private var delegate: ByteArrayInputStream? = null + + private val d: InputStream get() = delegate ?: error("No data available") + + override fun read(): Int = d.read() + + fun updateDelegate(bytes: ByteArray) { + delegate = ByteArrayInputStream(bytes) + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1599989c8fa..c6b2732ac51 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,6 +15,8 @@ kotlin-node = "22.5.4-pre.818" # https://github.com/JetBrains/kotlin-wrappers bignum = "0.3.10" # https://github.com/ionspin/kotlin-multiplatform-bignum stately = "2.1.0" # https://github.com/touchlab/Stately fastZlib = "2.0.1" # https://github.com/timotejroiko/fast-zlib +zstd-jni = "1.5.6-7" # https://github.com/luben/zstd-jni +zstd-codec = "0.1.5" # https://www.npmjs.com/package/zstd-codec # code generation ksp = "2.0.21-1.0.25" # https://github.com/google/ksp @@ -63,6 +65,7 @@ kotlin-node = { module = "org.jetbrains.kotlin-wrappers:kotlin-node", version.re # JDK replacements bignum = { module = "com.ionspin.kotlin:bignum", version.ref = "bignum" } stately-collections = { module = "co.touchlab:stately-concurrent-collections", version.ref = "stately" } +zstd-jni = { module = "com.github.luben:zstd-jni", version.ref = "zstd-jni" } # code generation ksp-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 493392acc4e..dc20ca6dd7c 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -127,6 +127,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +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== + debug@^4.3.5: version "4.3.6" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" @@ -144,11 +149,33 @@ diff@^5.2.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== +duplex-maker@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/duplex-maker/-/duplex-maker-1.0.0.tgz#1604f8b943cb0063a6d3e1fe42aa65113a79da4a" + integrity sha512-KoHuzggxg7f+vvjqOHfXxaQYI1POzBm+ah0eec7YDssZmbt6QFBI8d1nl5GQwAgR2f+VQCPvyvZtmWWqWuFtlA== + +duplexify@^3.5.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + 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== +end-of-stream@^1.0.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -245,7 +272,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2: +inherits@2, 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== @@ -289,6 +316,16 @@ is-unicode-supported@^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-zst@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-zst/-/is-zst-1.0.0.tgz#97462bb1a376dabba561e249ea754801e9b90fe0" + integrity sha512-ZA5lvshKAl8z30dX7saXLpVhpsq3d2EHK9uf7qtUjnOtdw4XBpAoWb2RvZ5kyoaebdoidnGI0g2hn9Z7ObPbww== + +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== + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -366,7 +403,7 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -once@^1.3.0: +once@^1.3.0, once@^1.4.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== @@ -392,11 +429,32 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== +peek-stream@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/peek-stream/-/peek-stream-1.1.3.tgz#3b35d84b7ccbbd262fff31dc10da56856ead6d67" + integrity sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA== + dependencies: + buffer-from "^1.0.0" + duplexify "^3.5.0" + through2 "^2.0.3" + picomatch@^2.0.4, picomatch@^2.2.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +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== + +process-streams@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/process-streams/-/process-streams-1.0.3.tgz#8df3e807932fc80cbb2ab92dd7c6f199c5faa9b1" + integrity sha512-xkIaM5vYnyekB88WyET78YEqXiaJRy0xcvIdE22n+myhvBT7LlLmX6iAtq7jDvVH8CUx2rqQsd32JdRyJMV3NA== + dependencies: + duplex-maker "^1.0.0" + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -404,6 +462,28 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" +readable-stream@3: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@^2.0.0, readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + 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" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -416,11 +496,16 @@ require-directory@^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== -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-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== + serialize-javascript@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" @@ -428,6 +513,16 @@ serialize-javascript@^6.0.2: dependencies: randombytes "^2.1.0" +simple-zstd@1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/simple-zstd/-/simple-zstd-1.4.2.tgz#4f5b7b05dfd2930b03092eb0c0cd13a44bad4b34" + integrity sha512-kGYEvT33M5XfyQvvW4wxl3eKcWbdbCc1V7OZzuElnaXft0qbVzoIIXHXiCm3JCUki+MZKKmvjl8p2VGLJc5Y/A== + dependencies: + is-zst "^1.0.0" + peek-stream "^1.1.3" + process-streams "^1.0.1" + through2 "^4.0.2" + source-map-support@0.5.21: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -441,6 +536,11 @@ source-map@^0.6.0: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +stream-shift@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== + 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" @@ -450,6 +550,20 @@ string-width@^4.1.0, string-width@^4.2.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" @@ -476,6 +590,21 @@ supports-color@^8.1.1: dependencies: has-flag "^4.0.0" +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through2@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764" + integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw== + dependencies: + readable-stream "3" + 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" @@ -493,6 +622,11 @@ typescript@5.5.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== +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== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -530,6 +664,11 @@ ws@8.5.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== +xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -567,3 +706,8 @@ 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== + +zstd-codec@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/zstd-codec/-/zstd-codec-0.1.5.tgz#c180193e4603ef74ddf704bcc835397d30a60e42" + integrity sha512-v3fyjpK8S/dpY/X5WxqTK3IoCnp/ZOLxn144GZVlNUjtwAchzrVo03h+oMATFhCIiJ5KTr4V3vDQQYz4RU684g== diff --git a/samples/src/commonMain/resources/simplelogger.properties b/samples/src/commonMain/resources/simplelogger.properties new file mode 100644 index 00000000000..b4378621551 --- /dev/null +++ b/samples/src/commonMain/resources/simplelogger.properties @@ -0,0 +1,2 @@ +org.slf4j.simpleLogger.defaultLogLevel=trace +org.slf4j.simpleLogger.showDateTime=true \ No newline at end of file