diff --git a/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/NpmPinTarget.kt b/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/NpmPinTarget.kt new file mode 100644 index 000000000..7bd442c02 --- /dev/null +++ b/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/NpmPinTarget.kt @@ -0,0 +1,35 @@ +package sk.ainet.buildlogic.npm + +/** + * Which Yarn root — and so which committed lockfile — a pin applies to. + * + * Most pins want both, which is the default. Scope a pin when the package exists in + * only one of the two dependency graphs, because Yarn writes a lockfile entry for + * **every** `resolutions` key whether or not anything in that graph requests the + * package. An unscoped `webpack` pin therefore adds webpack and its ~76 transitive + * packages to `kotlin-js-store/wasm/yarn.lock`, which bundles nothing with webpack — + * they would be downloaded and installed by the wasm build for no reason, and + * Dependabot would start reporting them against a lockfile that never uses them. + * + * Check which graph actually holds a package before scoping a pin: + * + * ``` + * grep -c '^webpack@' kotlin-js-store/yarn.lock kotlin-js-store/wasm/yarn.lock + * ``` + */ +enum class NpmPinTarget { + + /** `kotlin-js-store/yarn.lock`, driven by the `js` target's Yarn root. */ + JS, + + /** `kotlin-js-store/wasm/yarn.lock`, driven by the `wasmJs` target's Yarn root. */ + WASM, + + ; + + companion object { + + /** The default scope of [NpmPinsExtension.pin]: force the version everywhere. */ + val ALL: Set = entries.toSet() + } +} diff --git a/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/NpmPinsExtension.kt b/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/NpmPinsExtension.kt index b81b3b353..bf04a7a7d 100644 --- a/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/NpmPinsExtension.kt +++ b/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/NpmPinsExtension.kt @@ -31,30 +31,48 @@ import org.gradle.api.provider.Provider * pin("socket.io", libs.versions.npm.socketio) * pin("@types/node", libs.versions.npm.typesNode) * ``` + * + * ## Scoping a pin to one lockfile + * + * A pin applies to both Yarn roots unless told otherwise. Pass [NpmPinTarget] values + * when the package lives in only one graph, so the other lockfile does not acquire an + * entry — and a whole transitive tree — for a package it never resolves: + * + * ```kotlin + * pin("webpack", libs.versions.npm.webpack, NpmPinTarget.JS) + * ``` */ abstract class NpmPinsExtension { /** - * Package name -> exact version, as declared by [pin]. Consumed by + * Package name -> exact version for `kotlin-js-store/yarn.lock`. Consumed by * [NpmPinsPlugin] and [VerifyNpmPinsTask]; declare pins through [pin] rather than * mutating this directly, which skips validation and duplicate detection. */ - abstract val pins: MapProperty + abstract val jsPins: MapProperty + + /** Package name -> exact version for `kotlin-js-store/wasm/yarn.lock`. See [jsPins]. */ + abstract val wasmPins: MapProperty /** - * Whether `verifyNpmPins` fails when a pinned package is absent from every - * lockfile. Defaults to `false`: a pin that outlives its package (because the - * Kotlin toolchain dropped the dependency) is stale rather than broken, and + * Whether `verifyNpmPins` fails when a pinned package is absent from the lockfile + * it is scoped to. Defaults to `false`: a pin that outlives its package (because + * the Kotlin toolchain dropped the dependency) is stale rather than broken, and * should be reported without breaking the build. */ abstract val failOnMissingPackage: Property private val declared = mutableSetOf() - /** Pins [packageName] to a version held in the version catalog. */ - fun pin(packageName: String, version: Provider) { + /** + * Pins [packageName] to a version held in the version catalog. + * + * With no [targets] the pin applies to every lockfile; name them to restrict it. + */ + fun pin(packageName: String, version: Provider, vararg targets: NpmPinTarget) { val name = validatePackageName(packageName) - pins.put(name, version.map { validateVersion(name, it) }) + val checked = version.map { validateVersion(name, it) } + scopeOf(targets).forEach { target -> mapFor(target).put(name, checked) } } /** @@ -63,9 +81,18 @@ abstract class NpmPinsExtension { * Prefer the [Provider] overload — a number in `libs.versions.toml` is visible to * dependency-update tooling, a number in the build script is not. */ - fun pin(packageName: String, version: String) { + fun pin(packageName: String, version: String, vararg targets: NpmPinTarget) { val name = validatePackageName(packageName) - pins.put(name, validateVersion(name, version)) + val checked = validateVersion(name, version) + scopeOf(targets).forEach { target -> mapFor(target).put(name, checked) } + } + + private fun scopeOf(targets: Array): Set = + if (targets.isEmpty()) NpmPinTarget.ALL else targets.toSet() + + private fun mapFor(target: NpmPinTarget): MapProperty = when (target) { + NpmPinTarget.JS -> jsPins + NpmPinTarget.WASM -> wasmPins } private fun validatePackageName(packageName: String): String { @@ -75,8 +102,9 @@ abstract class NpmPinsExtension { "[npm-pins] Package name '$packageName' must not contain whitespace" } require(declared.add(name)) { - "[npm-pins] '$name' is pinned twice — a Yarn resolution is global, so the " + - "second declaration would silently win" + "[npm-pins] '$name' is pinned twice — a Yarn resolution is global within a " + + "Yarn root, so the second declaration would silently win. Declare it " + + "once and pass both targets, or scope each pin to a different target." } return name } diff --git a/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/NpmPinsPlugin.kt b/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/NpmPinsPlugin.kt index 3981a6cde..0b9ab550f 100644 --- a/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/NpmPinsPlugin.kt +++ b/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/NpmPinsPlugin.kt @@ -27,7 +27,8 @@ import sk.ainet.buildlogic.root.SkainetRootExtension * * There are two such extensions — one for JS, one for Wasm — each with its own * lockfile, so a pin has to be applied twice. This plugin does that from a single - * declaration. + * declaration, and lets a pin opt out of one of them via [NpmPinTarget] when the + * package exists in only one graph. * * ## Declaring a pin * @@ -42,6 +43,9 @@ import sk.ainet.buildlogic.root.SkainetRootExtension * skainet { * npmPins { * pin("ws", libs.versions.npm.ws) + * // Only the JS graph bundles with webpack; scoping keeps webpack's ~76 + * // transitive packages out of kotlin-js-store/wasm/yarn.lock. + * pin("webpack", libs.versions.npm.webpack, NpmPinTarget.JS) * } * } * ``` @@ -75,30 +79,31 @@ class NpmPinsPlugin : Plugin { // Resolved lazily: pins are declared in the root script body, which runs after // the plugins block that applies this plugin. - val pinsProvider: Provider> = extension.pins + val jsPins: Provider> = extension.jsPins + val wasmPins: Provider> = extension.wasmPins // The Yarn plugins are applied by KGP only once a js/wasmJs target is configured, // which happens well after this plugin is applied — hence the reactive hooks. + // Each root gets only the pins scoped to it; see NpmPinTarget for why that matters. project.plugins.withType(YarnPlugin::class.java) { - project.extensions.getByType(YarnRootExtension::class.java).applyPins(pinsProvider.get()) + project.extensions.getByType(YarnRootExtension::class.java).applyPins(jsPins.get()) } project.plugins.withType(WasmYarnPlugin::class.java) { // getByName rather than WasmYarnRootExtension[project]: the latter applies // WasmYarnPlugin as a side effect, dragging wasm Yarn setup into js-only builds. val wasmYarn = project.extensions.getByName(WasmYarnRootExtension.YARN) as WasmYarnRootExtension - wasmYarn.applyPins(pinsProvider.get()) + wasmYarn.applyPins(wasmPins.get()) } val verify = project.tasks.register("verifyNpmPins", VerifyNpmPinsTask::class.java) { group = "verification" description = "Check the committed Yarn lockfiles against the pins declared in skainet { npmPins { } }" - pins.set(pinsProvider) + this.jsPins.set(jsPins) + this.wasmPins.set(wasmPins) failOnMissingPackage.set(extension.failOnMissingPackage) rootDirectory.set(project.layout.projectDirectory) - lockFiles.from( - project.layout.projectDirectory.file("kotlin-js-store/yarn.lock"), - project.layout.projectDirectory.file("kotlin-js-store/wasm/yarn.lock"), - ) + jsLockFile.from(project.layout.projectDirectory.file("kotlin-js-store/yarn.lock")) + wasmLockFile.from(project.layout.projectDirectory.file("kotlin-js-store/wasm/yarn.lock")) // The lockfiles are outputs of the store tasks. Order after them rather than // depending on them, so `verifyNpmPins` stays a cheap file check on its own but // still sees the current state when a full build refreshes the lockfiles. diff --git a/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/VerifyNpmPinsTask.kt b/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/VerifyNpmPinsTask.kt index 58d98f6ca..a2720c6ed 100644 --- a/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/VerifyNpmPinsTask.kt +++ b/build-logic/convention/src/main/kotlin/sk/ainet/buildlogic/npm/VerifyNpmPinsTask.kt @@ -13,6 +13,7 @@ import org.gradle.api.tasks.PathSensitive import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskAction import org.gradle.work.DisableCachingByDefault +import java.io.File /** * Fails when a committed Yarn lockfile disagrees with a declared npm pin. @@ -20,21 +21,33 @@ import org.gradle.work.DisableCachingByDefault * Yarn `resolutions` make the pin take effect, but only the next time the lockfile * is regenerated. Without this check a stale or hand-edited lockfile silently wins * — which is exactly how PR #894's `ws` bump ended up as a zero-line diff. + * + * Each lockfile is checked against its own pin map, so a pin scoped to one + * [NpmPinTarget] is never reported as missing from the other lockfile. */ @DisableCachingByDefault(because = "Reads two small lockfiles; caching costs more than it saves") abstract class VerifyNpmPinsTask : DefaultTask() { - /** Package name -> pinned version, sourced from the `npm-*` catalog aliases. */ + /** Package name -> pinned version for the Kotlin/JS lockfile. */ + @get:Input + abstract val jsPins: MapProperty + + /** Package name -> pinned version for the Kotlin/Wasm lockfile. */ @get:Input - abstract val pins: MapProperty + abstract val wasmPins: MapProperty @get:Input abstract val failOnMissingPackage: Property - /** The committed lockfiles under `kotlin-js-store/`. Missing files are skipped. */ + /** `kotlin-js-store/yarn.lock`. Missing file is skipped. */ + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val jsLockFile: ConfigurableFileCollection + + /** `kotlin-js-store/wasm/yarn.lock`. Missing file is skipped. */ @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) - abstract val lockFiles: ConfigurableFileCollection + abstract val wasmLockFile: ConfigurableFileCollection /** Only used to render lockfile paths relative to the repository root in messages. */ @get:Internal @@ -42,31 +55,49 @@ abstract class VerifyNpmPinsTask : DefaultTask() { @TaskAction fun verify() { - val expected = pins.get() - if (expected.isEmpty()) { + val lanes = listOf( + Lane("Kotlin/JS", jsPins.get(), jsLockFile.files), + Lane("Kotlin/Wasm", wasmPins.get(), wasmLockFile.files), + ) + + val pinnedPackages = lanes.flatMap { it.pins.keys }.toSortedSet() + if (pinnedPackages.isEmpty()) { logger.lifecycle("[npm-pins] No npm pins declared; nothing to verify.") return } - val mismatches = mutableListOf() - val seen = mutableSetOf() val rootDir = rootDirectory.get().asFile + val mismatches = mutableListOf() + val missing = mutableListOf() + var checkedLockFiles = 0 + + for (lane in lanes) { + if (lane.pins.isEmpty()) continue + val lockFile = lane.lockFiles.firstOrNull { it.isFile } ?: continue + checkedLockFiles++ - lockFiles.files.filter { it.isFile }.sortedBy { it.path }.forEach { lockFile -> val relative = lockFile.relativeToOrSelf(rootDir).path + val seen = mutableSetOf() YarnLockParser.parse(lockFile.readText()).forEach { (packageName, version) -> - val pinned = expected[packageName] ?: return@forEach + val pinned = lane.pins[packageName] ?: return@forEach seen += packageName if (version != pinned) { mismatches += "$relative: $packageName resolved to $version, pinned to $pinned" } } + (lane.pins.keys - seen).sorted().forEach { missing += "$relative (${lane.label}): $it" } } - val missing = expected.keys - seen if (missing.isNotEmpty()) { - val message = "[npm-pins] Pinned but absent from every lockfile: ${missing.sorted().joinToString(", ")}. " + - "The pin may be stale — drop it from gradle/libs.versions.toml if the package is gone for good." + val message = buildString { + appendLine("[npm-pins] Pinned but absent from the lockfile the pin is scoped to:") + missing.sorted().forEach { appendLine(" - $it") } + append( + "The pin may be stale — drop it from gradle/libs.versions.toml if the " + + "package is gone for good, or narrow its NpmPinTarget if it only ever " + + "existed in the other graph." + ) + } if (failOnMissingPackage.get()) throw GradleException(message) logger.warn(message) } @@ -84,6 +115,10 @@ abstract class VerifyNpmPinsTask : DefaultTask() { ) } - logger.lifecycle("[npm-pins] ${expected.size} pin(s) verified against ${lockFiles.files.count { it.isFile }} lockfile(s).") + logger.lifecycle( + "[npm-pins] ${pinnedPackages.size} pin(s) verified against $checkedLockFiles lockfile(s)." + ) } + + private data class Lane(val label: String, val pins: Map, val lockFiles: Set) } diff --git a/build.gradle.kts b/build.gradle.kts index 68337f7bd..b7617fff1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +import sk.ainet.buildlogic.npm.NpmPinTarget + plugins { alias(libs.plugins.androidLibrary) apply false alias(libs.plugins.kotlinMultiplatform) apply false @@ -19,16 +21,24 @@ allprojects { version = providers.gradleProperty("VERSION_NAME").getOrElse("unspecified") } -// Root-project SKaiNET conventions. npm pins are forced onto both kotlin-js-store +// Root-project SKaiNET conventions. npm pins are forced onto the kotlin-js-store // lockfiles via Yarn resolutions; see docs "Pinning npm Packages". +// +// `ws` is the only pinned package present in both dependency graphs, so it is the only +// unscoped pin. Everything else lives solely in the Kotlin/JS graph and is scoped to it: +// Yarn writes a lockfile entry for every resolutions key whether or not that graph +// requests the package, so an unscoped pin would add the package — and, for webpack, its +// ~76 transitive dependencies — to kotlin-js-store/wasm/yarn.lock for nothing. skainet { npmPins { pin("ws", libs.versions.npm.ws) - pin("js-yaml", libs.versions.npm.js.yaml) - pin("socket.io-parser", libs.versions.npm.socketio.parser) - pin("fast-uri", libs.versions.npm.fast.uri) - pin("serialize-javascript", libs.versions.npm.serialize.javascript) - pin("brace-expansion", libs.versions.npm.brace.expansion) + pin("js-yaml", libs.versions.npm.js.yaml, NpmPinTarget.JS) + pin("socket.io-parser", libs.versions.npm.socketio.parser, NpmPinTarget.JS) + pin("fast-uri", libs.versions.npm.fast.uri, NpmPinTarget.JS) + pin("serialize-javascript", libs.versions.npm.serialize.javascript, NpmPinTarget.JS) + pin("brace-expansion", libs.versions.npm.brace.expansion, NpmPinTarget.JS) + pin("diff", libs.versions.npm.diff, NpmPinTarget.JS) + pin("webpack", libs.versions.npm.webpack, NpmPinTarget.JS) } } diff --git a/docs/modules/ROOT/pages/contributing/build-from-source.adoc b/docs/modules/ROOT/pages/contributing/build-from-source.adoc index a6247f27e..ebe3cd226 100644 --- a/docs/modules/ROOT/pages/contributing/build-from-source.adoc +++ b/docs/modules/ROOT/pages/contributing/build-from-source.adoc @@ -194,6 +194,35 @@ skainet { ./gradlew kotlinUpgradeYarnLock kotlinWasmUpgradeYarnLock ---- +==== Scoping a pin to one lockfile + +Yarn writes a lockfile entry for *every* `resolutions` key, whether or not that dependency graph actually requests the package. An unscoped pin for a package that only the JS graph uses therefore adds it — and everything it depends on — to `kotlin-js-store/wasm/yarn.lock`, where nothing imports it. For `webpack` that is roughly 76 extra packages the Wasm build would download and install for nothing, and which Dependabot would then report against a lockfile that never uses them. + +Pass an `NpmPinTarget` when a package lives in only one graph: + +[source,kotlin] +---- +import sk.ainet.buildlogic.npm.NpmPinTarget + +skainet { + npmPins { + pin("ws", libs.versions.npm.ws) // <1> + pin("webpack", libs.versions.npm.webpack, NpmPinTarget.JS) // <2> + } +} +---- +<1> No target: applies to both lockfiles. Correct for `ws`, which both graphs resolve. +<2> `NpmPinTarget.JS`: only `kotlin-js-store/yarn.lock` gets the resolution. + +Check which graph holds a package before deciding: + +[source,bash] +---- +grep -c '^webpack@' kotlin-js-store/yarn.lock kotlin-js-store/wasm/yarn.lock +---- + +`verifyNpmPins` checks each lockfile against its own pin map, so a scoped pin is never reported as missing from the lockfile it was never meant to reach. + `verifyNpmPins` re-reads the committed lockfiles and fails if any pinned package resolved elsewhere. It is wired into `check` and runs on the `js-wasm` leg of `.github/workflows/build.yml`. The root plugin is not optional for web modules: `sk.ainet.multiplatform` fails at configuration time if a module builds `js`/`wasmJs` while the root project does not apply `sk.ainet.npm-pins`. Without it no `resolutions` are written *and* `verifyNpmPins` does not exist to notice — a silent security regression rather than a build error. diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 350878db8..9481c056c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -37,10 +37,12 @@ kotest = "6.2.2" # Never edit kotlin-js-store/**/yarn.lock by hand — it is generated and will be # overwritten (see PR #894). # -# Expect a pin to show up in BOTH lockfiles even when only one graph uses the -# package: Yarn writes an entry for every `resolutions` key, matched or not. That -# is why kotlin-js-store/wasm/yarn.lock lists packages the wasm build never -# imports. Harmless, and the price of a single pin covering both targets. +# A pin lands in BOTH lockfiles by default, because Yarn writes an entry for every +# `resolutions` key whether or not that graph requests the package. Scope the pin +# when only one graph has it: +# pin("webpack", libs.versions.npm.webpack, NpmPinTarget.JS) +# Check which graph holds a package before deciding: +# grep -c '^webpack@' kotlin-js-store/yarn.lock kotlin-js-store/wasm/yarn.lock npm-ws = "8.21.1" # GHSA-96hv-2xvq-fx4p npm-js-yaml = "4.3.1" # GHSA-5p4m-2wfm-xmqj npm-socketio-parser = "4.2.7" # GHSA-2m8v-j782-fhvr @@ -51,6 +53,13 @@ npm-serialize-javascript = "7.0.5" # GHSA-5c6j-r48x-rmvq, GHSA-qj8w-gfj5-8c6v # set of both advisories (<1.1.18 and >=2.0.0 <2.1.4); the exported API is unchanged # between the two majors, so the 3.x consumer is unaffected. npm-brace-expansion = "2.1.4" # GHSA-rgw5-rvv9-x895, GHSA-mh99-v99m-4gvg +npm-diff = "8.0.3" # GHSA-73rr-hh4g-fpgx +# KGP pins webpack to an exact version (5.101.3 for Kotlin 2.4.10), so this +# resolution deliberately overrides the Kotlin toolchain's own choice. 5.104.1 is +# the first release clearing both advisories. Re-check this pin on every Kotlin +# upgrade: once KGP's own webpack moves past 5.104.1, drop the pin rather than +# holding the bundler behind the version KGP was tested against. +npm-webpack = "5.104.1" # GHSA-8fgc-7cc6-rx7x, GHSA-38r7-794h-5758 [libraries] jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jacksonDatabind" } diff --git a/kotlin-js-store/wasm/yarn.lock b/kotlin-js-store/wasm/yarn.lock index 00218d347..d12e41c53 100644 --- a/kotlin-js-store/wasm/yarn.lock +++ b/kotlin-js-store/wasm/yarn.lock @@ -2,65 +2,6 @@ # yarn lockfile v1 -"@socket.io/component-emitter@~3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" - integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== - -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== - -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== - -brace-expansion@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.4.tgz#589dab11c0018d0366be64cd8bf12c8dbecc8326" - integrity sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg== - dependencies: - balanced-match "^1.0.0" - -debug@~4.4.1: - version "4.4.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" - integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== - dependencies: - ms "^2.1.3" - -fast-uri@3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.5.tgz#610f37419a030270430cecd68d74e3d4d96725d0" - integrity sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw== - -js-yaml@4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.3.1.tgz#01216c001d67f48e2cd560d708c7af21090a3848" - integrity sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ== - dependencies: - argparse "^2.0.1" - -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== - -serialize-javascript@7.0.5: - version "7.0.5" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-7.0.5.tgz#c798cc0552ffbb08981914a42a8756e339d0d5b1" - integrity sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw== - -socket.io-parser@4.2.7: - version "4.2.7" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.7.tgz#679e51fe24d1c81df90fc5f7efe4a5f432fe99c0" - integrity sha512-IH/iSeO9T6gz1KkFleGDWkG9N3dl4jXVYUtMhIqH10Md0ttMer8nUNWiP1DKuNrybD2xBrixLJdCC9J6ECoYkg== - dependencies: - "@socket.io/component-emitter" "~3.1.0" - debug "~4.4.1" - ws@8.20.1, ws@8.21.1: version "8.21.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.21.1.tgz#045650cd4b1207809e7547146223c3814a9af586" diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 557136ade..508c036c5 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -348,10 +348,10 @@ base64id@2.0.0, base64id@~2.0.0: resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== -baseline-browser-mapping@^2.10.42: - version "2.10.43" - resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.43.tgz#7b5d11590ce5acdbe4859443e3c940e81ce8c02d" - integrity sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ== +baseline-browser-mapping@^2.11.12: + version "2.11.13" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.13.tgz#660073103c1bee93e54df55f117b7528adf6af19" + integrity sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ== binary-extensions@^2.0.0: version "2.3.0" @@ -395,16 +395,16 @@ browser-stdout@^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.24.0: - version "4.28.5" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.5.tgz#438b7d38c0d4b47740bbb36778d5bdca01b37838" - integrity sha512-Cu2E6QejHWzuDMTkuwgpABFgDfZrXLQq5V13YOACZx4mFAG4IwGTbTfHPMr4WtxlHoXSM8FIuRwYYCz5XiabaQ== +browserslist@^4.28.1: + version "4.28.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.8.tgz#a3c79ceb70028527e5da7dafc887f3200b5168c0" + integrity sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA== dependencies: - baseline-browser-mapping "^2.10.42" - caniuse-lite "^1.0.30001800" - electron-to-chromium "^1.5.387" - node-releases "^2.0.50" - update-browserslist-db "^1.2.3" + baseline-browser-mapping "^2.11.12" + caniuse-lite "^1.0.30001809" + electron-to-chromium "^1.5.402" + node-releases "^2.0.53" + update-browserslist-db "^1.3.0" buffer-from@^1.0.0: version "1.1.2" @@ -437,10 +437,10 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001800: - version "1.0.30001803" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001803.tgz#b2a5d696e042bc8304dcd4942c39fe330fbbcb24" - integrity sha512-g/uHREV2ZpK9qMalCsWaxmA6ol+DX8GYhuf3T40RKoP+oL7vhRJh8LNt73PCjpnR6l14FzfPrB5Yux4PKm2meg== +caniuse-lite@^1.0.30001809: + version "1.0.30001809" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz#e6cf71f14ddfe008f114dd2a846923be3c03a07b" + integrity sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ== chalk@^4.1.0: version "4.1.2" @@ -612,10 +612,10 @@ di@^0.0.1: resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" integrity sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA== -diff@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-7.0.0.tgz#3fb34d387cd76d803f6eebea67b921dab0182a9a" - integrity sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw== +diff@8.0.3, diff@^7.0.0: + version "8.0.3" + resolved "https://registry.yarnpkg.com/diff/-/diff-8.0.3.tgz#c7da3d9e0e8c283bb548681f8d7174653720c2d5" + integrity sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ== dom-serialize@^2.2.1: version "2.2.1" @@ -646,10 +646,10 @@ ee-first@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.5.387: - version "1.5.389" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.389.tgz#538be9ebec78026d4daba6be321ab854dfac2a8f" - integrity sha512-cEto7aeOqBfU1D+c5py5pE+ooscKE75JifxLBdFUZsqAxRS6y7kebtxAZvICszSl05gPjYHDTjY+lXpyGvpJbg== +electron-to-chromium@^1.5.402: + version "1.5.403" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.403.tgz#8a6e422bc68c5d2fa4d8c5fa2ba9a583c3d4452c" + integrity sha512-MQsYmdaLzvaCX5j+ZZBr5Fm6uCCnPQcRtlvmvRlWqrXy+BH2O4ffXIAScF+JQznQWB9brWp4lSD9Z4yNmaf2BA== emoji-regex@^8.0.0: version "8.0.0" @@ -687,10 +687,10 @@ engine.io@~6.6.0: engine.io-parser "~5.2.1" ws "~8.21.0" -enhanced-resolve@^5.17.3: - version "5.24.2" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.24.2.tgz#f25d703a24431cb1e02f944adb74aefa4fcb8d7e" - integrity sha512-rpsZEGT1jFuve6QlpyRp9ckQ+kN61hvF9BzCPyMdaKTm8UJce96KBn3sorXOFXlzjPrs3Vc4T1NsSroZ3PxlFw== +enhanced-resolve@^5.17.4: + version "5.24.5" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz#b4dad3255b7545f07ba5535189868e9f85f47573" + integrity sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A== dependencies: graceful-fs "^4.2.4" tapable "^2.3.3" @@ -720,10 +720,10 @@ es-errors@^1.3.0: resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-module-lexer@^1.2.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" - integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== +es-module-lexer@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-2.3.1.tgz#5bf2df06999dbbe5f006a5f46a11fb9f5b7b391b" + integrity sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA== es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: version "1.1.2" @@ -1250,7 +1250,7 @@ kotlin-web-helpers@3.0.0: dependencies: format-util "^1.0.5" -loader-runner@^4.2.0: +loader-runner@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.2.tgz#9913d3a15971f8f635915e601fb5c9d495d918e9" integrity sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w== @@ -1408,10 +1408,10 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -node-releases@^2.0.50: - version "2.0.51" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.51.tgz#cdc08433577f5b32ad01694481726e22eeb54aef" - integrity sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ== +node-releases@^2.0.53: + version "2.0.53" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.53.tgz#0fe5ad8a7935e075172f574e56f0c20f07fa41af" + integrity sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" @@ -1652,7 +1652,7 @@ safe-regex-test@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -schema-utils@^4.3.0, schema-utils@^4.3.2: +schema-utils@^4.3.0, schema-utils@^4.3.3: version "4.3.3" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.3.tgz#5b1850912fa31df90716963d45d9121fdfc09f46" integrity sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA== @@ -1882,12 +1882,12 @@ supports-preserve-symlinks-flag@^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.3.3: +tapable@^2.3.0, tapable@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.3.tgz#5da7c9992c46038221267985ab28421a8879f160" integrity sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A== -terser-webpack-plugin@^5.3.11: +terser-webpack-plugin@^5.3.16: version "5.6.1" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz#47bc41bd8b8fab8383b62ec763b7394829097e7b" integrity sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ== @@ -1952,10 +1952,10 @@ unpipe@~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.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" - integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== +update-browserslist-db@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.3.0.tgz#9ff2604d5b949051639c01a223a16619f8a2b2c7" + integrity sha512-x/M6q3w4Ybp91CNaS4S69UnliqR3BzRpOT6LWbksjth0S/+jhfaPJsWjt/TewpT8j9eLIojUf5jr29WextHroA== dependencies: escalade "^3.2.0" picocolors "^1.1.1" @@ -1975,7 +1975,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.4.1: +watchpack@^2.4.4: version "2.5.2" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.5.2.tgz#e12e82d84674266fc1c6dbfe38891b92ff0522ec" integrity sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg== @@ -2022,10 +2022,10 @@ webpack-sources@^3.3.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.5.1.tgz#76c2418486dcc02b2aa0694c104176c2858fe84a" integrity sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw== -webpack@5.101.3: - version "5.101.3" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.101.3.tgz#3633b2375bb29ea4b06ffb1902734d977bc44346" - integrity sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A== +webpack@5.101.3, webpack@5.104.1: + version "5.104.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.104.1.tgz#94bd41eb5dbf06e93be165ba8be41b8260d4fb1a" + integrity sha512-Qphch25abbMNtekmEGJmeRUhLDbe+QfiWTiqpKYkpCOWY64v9eyl+KRRLmqOFA2AvKPpc9DC6+u2n76tQLBoaA== dependencies: "@types/eslint-scope" "^3.7.7" "@types/estree" "^1.0.8" @@ -2035,22 +2035,22 @@ webpack@5.101.3: "@webassemblyjs/wasm-parser" "^1.14.1" acorn "^8.15.0" acorn-import-phases "^1.0.3" - browserslist "^4.24.0" + browserslist "^4.28.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.17.3" - es-module-lexer "^1.2.1" + enhanced-resolve "^5.17.4" + es-module-lexer "^2.0.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" graceful-fs "^4.2.11" json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" + loader-runner "^4.3.1" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^4.3.2" - tapable "^2.1.1" - terser-webpack-plugin "^5.3.11" - watchpack "^2.4.1" + schema-utils "^4.3.3" + tapable "^2.3.0" + terser-webpack-plugin "^5.3.16" + watchpack "^2.4.4" webpack-sources "^3.3.3" which@^1.2.1: