├── .editorconfig ├── .github ├── ci-gradle.properties └── workflows │ └── Build.yml ├── .gitignore ├── LICENSE ├── README.md ├── build-logic ├── build.gradle.kts └── settings.gradle.kts ├── build.gradle.kts ├── cacheable-compiler ├── build.gradle.kts ├── gradle.properties └── src │ └── main │ └── kotlin │ └── com │ └── moriatsushi │ └── cacheable │ └── compiler │ ├── CacheableCompilerPluginRegistrar.kt │ ├── CacheableIrElementTransformer.kt │ ├── CacheableIrGenerationExtension.kt │ ├── declaration │ ├── CacheStoreClassDeclaration.kt │ ├── CacheableAnnotationDeclaration.kt │ ├── CacheableDeclarations.kt │ └── CoroutineCacheStoreClassDeclaration.kt │ └── factory │ ├── IrActualFunctionFactory.kt │ ├── IrCacheStoreFieldFactory.kt │ └── IrCacheableFunctionBodyFactory.kt ├── cacheable-core ├── build.gradle.kts ├── gradle.properties └── src │ ├── commonMain │ └── kotlin │ │ └── com │ │ └── moriatsushi │ │ └── cacheable │ │ ├── Cacheable.kt │ │ ├── CacheableConfiguration.kt │ │ ├── CacheableTimeProvider.kt │ │ └── internal │ │ ├── BaseCacheStore.kt │ │ ├── CacheEntry.kt │ │ ├── CacheStore.kt │ │ ├── CoroutineCacheStore.kt │ │ ├── DefaultTimeProvider.kt │ │ └── LockStore.kt │ └── commonTest │ └── kotlin │ └── com │ └── moriatsushi │ └── cacheable │ └── internal │ ├── CacheStoreTest.kt │ ├── CoroutineCacheStoreTest.kt │ └── LockStoreTest.kt ├── cacheable-gradle-plugin ├── build.gradle.kts ├── gradle.properties └── src │ └── main │ └── kotlin │ └── com │ └── moriatsushi │ └── cacheable │ └── gradle │ └── plugin │ └── CacheableCompilerPluginSupportPlugin.kt ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── kotlin-js-store └── yarn.lock ├── renovate.json ├── settings.gradle.kts └── test ├── build.gradle.kts └── src ├── commonMain └── kotlin │ └── com │ └── moriatsushi │ └── cacheable │ └── test │ ├── ClassWithCompanionObject.kt │ ├── CoroutinesClass.kt │ ├── SimpleClass.kt │ ├── SimpleEnumClass.kt │ ├── SimpleObject.kt │ ├── TopLevelFunction.kt │ └── WithMaxCountClass.kt ├── commonTest └── kotlin │ └── com │ └── moriatsushi │ └── cacheable │ └── test │ ├── ClassWithCompanionObjectTest.kt │ ├── CoroutinesClassTest.kt │ ├── FakeTimeProvider.kt │ ├── SimpleClassTest.kt │ ├── SimpleEnumClassTest.kt │ ├── SimpleObjectTest.kt │ ├── TopLevelFunctionTest.kt │ └── WithMaxCountClassTest.kt ├── jvmMain └── kotlin │ └── com │ └── moriatsushi │ └── cacheable │ └── test │ └── MultiThreadClass.kt └── jvmTest └── kotlin └── com └── moriatsushi └── cacheable └── test └── MultiThreadClassTest.kt /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | insert_final_newline = true 5 | 6 | [*.{kt,kts}] 7 | ij_kotlin_allow_trailing_comma = true 8 | ij_kotlin_allow_trailing_comma_on_call_site = true 9 | -------------------------------------------------------------------------------- /.github/ci-gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.daemon=false 2 | org.gradle.parallel=true 3 | org.gradle.workers.max=2 4 | org.gradle.jvmargs=-Xmx2g 5 | 6 | # kotlin 7 | kotlin.compiler.execution.strategy=in-process 8 | kotlin.native.ignoreDisabledTargets=true 9 | 10 | # other 11 | warningsAsErrors=true 12 | -------------------------------------------------------------------------------- /.github/workflows/Build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | concurrency: 10 | group: build-${{ github.ref }} 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | timeout-minutes: 60 17 | 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | 22 | - name: Validate Gradle Wrapper 23 | uses: gradle/wrapper-validation-action@v1 24 | 25 | - name: Copy CI gradle.properties 26 | run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties 27 | 28 | - name: Set up JDK 17 29 | uses: actions/setup-java@v4 30 | with: 31 | distribution: 'zulu' 32 | java-version: 17 33 | 34 | - name: Setup Gradle 35 | uses: gradle/gradle-build-action@v2 36 | with: 37 | gradle-home-cache-cleanup: true 38 | cache-read-only: ${{ github.ref != 'refs/heads/main' }} 39 | 40 | - name: Check spotless 41 | run: ./gradlew spotlessCheck --no-configuration-cache --stacktrace 42 | 43 | - name: Assemble main outputs for all the variants. 44 | run: ./gradlew assemble --stacktrace 45 | 46 | - name: Run local tests 47 | run: ./gradlew allTests --stacktrace 48 | 49 | - name: Upload test reports 50 | if: always() 51 | uses: actions/upload-artifact@v3 52 | with: 53 | name: test-reports 54 | path: '**/build/reports/tests' 55 | 56 | build-on-macos: 57 | runs-on: macos-latest 58 | timeout-minutes: 30 59 | 60 | steps: 61 | - name: Checkout 62 | uses: actions/checkout@v4 63 | 64 | - name: Validate Gradle Wrapper 65 | uses: gradle/wrapper-validation-action@v1 66 | 67 | - name: Copy CI gradle.properties 68 | run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties 69 | 70 | - name: Set up JDK 17 71 | uses: actions/setup-java@v4 72 | with: 73 | distribution: 'zulu' 74 | java-version: 17 75 | 76 | - name: Setup Gradle 77 | uses: gradle/gradle-build-action@v2 78 | with: 79 | gradle-home-cache-cleanup: true 80 | cache-read-only: ${{ github.ref != 'refs/heads/main' }} 81 | 82 | - name: Run local tests 83 | run: | 84 | ./gradlew iosX64Test iosSimulatorArm64Test \ 85 | macosX64Test macosArm64Test \ 86 | watchosX64Test watchosSimulatorArm64Test \ 87 | tvosX64Test tvosSimulatorArm64Test --stacktrace 88 | 89 | - name: Upload test reports 90 | if: always() 91 | uses: actions/upload-artifact@v3 92 | with: 93 | name: test-reports 94 | path: '**/build/reports/tests' 95 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .idea/**/* 5 | !.idea/inspectionProfiles/ 6 | !.idea/inspectionProfiles/** 7 | !.idea/codeStyles/ 8 | !.idea/codeStyles/** 9 | .DS_Store 10 | build/ 11 | /captures 12 | .externalNativeBuild 13 | .cxx 14 | local.properties 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kotlin Cacheable 2 | 3 | Kotlin Cacheable is an annotation-based caching library for Kotlin Multiplatform. 4 | 5 | ## Setup 6 | 7 | This library is published to Maven Central. 8 | Add the Maven Central repository to your project's `pluginManagement` and 9 | `dependencyResolutionManagement` sections. 10 | 11 | ```kotlin 12 | // setting.gradle.kts 13 | pluginManagement { 14 | repositories { 15 | mavenCentral() 16 | } 17 | } 18 | dependencyResolutionManagement { 19 | repositoriesMode.set(RepositoriesMode.PREFER_PROJECT) 20 | repositories { 21 | mavenCentral() 22 | } 23 | } 24 | ``` 25 | 26 | Enable the Gradle plugin for the module where you want to use this library. 27 | 28 | ```kotlin 29 | // build.gradle.kts 30 | plugins { 31 | kotlin(/* ... */) 32 | id("com.moriatsushi.cacheable") version "0.0.3" 33 | } 34 | ``` 35 | 36 | You also need to add the `cacheable-core` dependency to the module. 37 | 38 | ```kotlin 39 | // build.gradle.kts 40 | dependencies { 41 | implementation("com.moriatsushi.cacheable:cacheable-core:0.0.3") 42 | } 43 | ``` 44 | 45 | ## Basic Usage 46 | 47 | You can use `@Cacheable` annotation to cache the result of specified functions. 48 | When you call a function with this annotation, it will return the cached value if the function is 49 | called with the same arguments. 50 | 51 | Here is an example: 52 | 53 | ```kotlin 54 | @Cacheable 55 | fun getSomething(key: String): Something { 56 | /* ... */ 57 | } 58 | ``` 59 | 60 | This is equivalent to the following code: 61 | 62 | ```kotlin 63 | private var cache = mutableMapOf() 64 | 65 | fun getSomething(key: String): Something = 66 | cache.getOrPut(key) { /* ... */ } 67 | ``` 68 | 69 | If you use the cacheable function within a class, the cache is only shared within an instance of the 70 | class. 71 | 72 | You can also use `@Cacheable` annotation for a suspend function. 73 | 74 | ```kotlin 75 | class Repository(private val api: Api) { 76 | @Cacheable 77 | suspend fun getUser(id: String): User = 78 | api.getUser(id) 79 | } 80 | ``` 81 | 82 | ## APIs 83 | There are 2 parameters you can specify to `@Cacheable` annotation. 84 | 85 | * `maxCount`: The maximum number of cached values. If the number of cached values exceeds this 86 | value, the cache with the oldest access time will be removed. If you don't specify this parameter, 87 | the number of cached values will be unlimited. 88 | * `lock`: When this is `true`, the function is guaranteed to be called only once even if the 89 | function is called multiple times with the same arguments at the same time. Otherwise, the 90 | function may be called multiple times with the same arguments at the same time. The default value 91 | is false. 92 | 93 | ```kotlin 94 | class SomeClass { 95 | @Cacheable(maxCount = 10, lock = true) 96 | fun getSomething(key: String): Something { 97 | // ... 98 | } 99 | } 100 | ``` 101 | -------------------------------------------------------------------------------- /build-logic/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.kotlin.jvm) apply false 3 | } 4 | -------------------------------------------------------------------------------- /build-logic/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencyResolutionManagement { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | versionCatalogs { 7 | create("libs") { 8 | from(files("../gradle/libs.versions.toml")) 9 | } 10 | } 11 | } 12 | 13 | rootProject.name = "build-logic" 14 | include(":chacheable-gradle-plugin") 15 | project(":chacheable-gradle-plugin").projectDir = File("../cacheable-gradle-plugin") 16 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.diffplug.gradle.spotless.SpotlessExtension 2 | import com.diffplug.gradle.spotless.SpotlessPlugin 3 | 4 | plugins { 5 | alias(libs.plugins.kotlin.multiplatform) apply false 6 | alias(libs.plugins.kotlinx.atomicfu) apply false 7 | alias(libs.plugins.spotless) apply false 8 | alias(libs.plugins.maven.publish) 9 | } 10 | 11 | subprojects { 12 | apply() 13 | 14 | extensions.configure { 15 | kotlin { 16 | target("**/*.kt") 17 | val ktlintVersion = libs.versions.ktlint.get() 18 | targetExclude("**/build/**/*.kt") 19 | ktlint(ktlintVersion) 20 | .editorConfigOverride( 21 | mapOf( 22 | "ktlint_code_style" to "android", 23 | "ij_kotlin_allow_trailing_comma" to true, 24 | "ij_kotlin_allow_trailing_comma_on_call_site" to true, 25 | ), 26 | ) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /cacheable-compiler/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | alias(libs.plugins.ksp) 4 | alias(libs.plugins.maven.publish) 5 | } 6 | 7 | dependencies { 8 | compileOnly(libs.kotlin.compiler.embeddable) 9 | 10 | ksp(libs.auto.service.ksp) 11 | compileOnly(libs.auto.service.annotations) 12 | } 13 | -------------------------------------------------------------------------------- /cacheable-compiler/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=cacheable-compiler 2 | POM_NAME=Kotlin Cacheable 3 | POM_DESCRIPTION=An annotation-based caching library for Kotlin Multiplatform 4 | POM_PACKAGING=jar 5 | -------------------------------------------------------------------------------- /cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/CacheableCompilerPluginRegistrar.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.compiler 2 | 3 | import com.google.auto.service.AutoService 4 | import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension 5 | import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar 6 | import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi 7 | import org.jetbrains.kotlin.config.CompilerConfiguration 8 | 9 | @OptIn(ExperimentalCompilerApi::class) 10 | @AutoService(CompilerPluginRegistrar::class) 11 | class CacheableCompilerPluginRegistrar : CompilerPluginRegistrar() { 12 | override val supportsK2: Boolean get() = false 13 | 14 | override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) { 15 | IrGenerationExtension.registerExtension(CacheableIrGenerationExtension()) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/CacheableIrElementTransformer.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.compiler 2 | 3 | import com.moriatsushi.cacheable.compiler.declaration.CacheableDeclarations 4 | import com.moriatsushi.cacheable.compiler.factory.IrActualFunctionFactory 5 | import com.moriatsushi.cacheable.compiler.factory.IrCacheStoreFieldFactory 6 | import com.moriatsushi.cacheable.compiler.factory.IrCacheableFunctionBodyFactory 7 | import org.jetbrains.kotlin.ir.IrStatement 8 | import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer 9 | import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction 10 | import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid 11 | 12 | class CacheableIrElementTransformer( 13 | private val cacheableDeclarations: CacheableDeclarations, 14 | private val irCacheStoreFieldFactory: IrCacheStoreFieldFactory, 15 | private val irActualFunctionFactory: IrActualFunctionFactory, 16 | private val irCacheableFunctionBodyFactory: IrCacheableFunctionBodyFactory, 17 | ) : IrElementTransformerVoid() { 18 | override fun visitSimpleFunction(declaration: IrSimpleFunction): IrStatement { 19 | if (!cacheableDeclarations.cacheableAnnotationDeclaration.hasAnnotation(declaration)) { 20 | return declaration 21 | } 22 | 23 | val parent = (declaration.parent as? IrDeclarationContainer) 24 | ?: error("Unexpected function parent type") 25 | 26 | val irCacheStoreField = irCacheStoreFieldFactory.create(declaration) 27 | parent.declarations.add(irCacheStoreField) 28 | 29 | val actualFunction = irActualFunctionFactory.create(declaration) 30 | parent.declarations.add(actualFunction) 31 | 32 | declaration.body = irCacheableFunctionBodyFactory.create( 33 | originalFunction = declaration, 34 | actualFunction = actualFunction, 35 | cacheStoreField = irCacheStoreField, 36 | ) 37 | return declaration 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/CacheableIrGenerationExtension.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.compiler 2 | 3 | import com.moriatsushi.cacheable.compiler.declaration.CacheableDeclarations 4 | import com.moriatsushi.cacheable.compiler.factory.IrActualFunctionFactory 5 | import com.moriatsushi.cacheable.compiler.factory.IrCacheStoreFieldFactory 6 | import com.moriatsushi.cacheable.compiler.factory.IrCacheableFunctionBodyFactory 7 | import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension 8 | import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext 9 | import org.jetbrains.kotlin.ir.declarations.IrModuleFragment 10 | import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid 11 | 12 | class CacheableIrGenerationExtension : IrGenerationExtension { 13 | override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { 14 | moduleFragment.transformChildrenVoid(createCacheableIrElementTransformer(pluginContext)) 15 | } 16 | 17 | private fun createCacheableIrElementTransformer( 18 | pluginContext: IrPluginContext, 19 | ): CacheableIrElementTransformer { 20 | val cacheableDeclarations = CacheableDeclarations.find(pluginContext) 21 | ?: error("Please check the dependency for kotlin-cacheable") 22 | val irCacheStoreFieldFactory = IrCacheStoreFieldFactory( 23 | pluginContext.irFactory, 24 | cacheableDeclarations, 25 | ) 26 | val irActualFunctionFactory = IrActualFunctionFactory(pluginContext.irFactory) 27 | val irCacheableFunctionBodyFactory = IrCacheableFunctionBodyFactory( 28 | pluginContext.irBuiltIns, 29 | pluginContext.irFactory, 30 | cacheableDeclarations, 31 | ) 32 | return CacheableIrElementTransformer( 33 | cacheableDeclarations = cacheableDeclarations, 34 | irCacheStoreFieldFactory = irCacheStoreFieldFactory, 35 | irActualFunctionFactory = irActualFunctionFactory, 36 | irCacheableFunctionBodyFactory = irCacheableFunctionBodyFactory, 37 | ) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/declaration/CacheStoreClassDeclaration.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.compiler.declaration 2 | 3 | import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext 4 | import org.jetbrains.kotlin.ir.IrBuiltIns 5 | import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET 6 | import org.jetbrains.kotlin.ir.expressions.IrCall 7 | import org.jetbrains.kotlin.ir.expressions.IrConstructorCall 8 | import org.jetbrains.kotlin.ir.expressions.IrExpression 9 | import org.jetbrains.kotlin.ir.expressions.IrVarargElement 10 | import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl 11 | import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl 12 | import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl 13 | import org.jetbrains.kotlin.ir.symbols.IrClassSymbol 14 | import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol 15 | import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol 16 | import org.jetbrains.kotlin.ir.types.IrSimpleType 17 | import org.jetbrains.kotlin.ir.types.IrType 18 | import org.jetbrains.kotlin.ir.types.createType 19 | import org.jetbrains.kotlin.ir.types.typeWith 20 | import org.jetbrains.kotlin.ir.util.constructors 21 | import org.jetbrains.kotlin.ir.util.functions 22 | import org.jetbrains.kotlin.name.ClassId 23 | import org.jetbrains.kotlin.name.FqName 24 | import org.jetbrains.kotlin.name.Name 25 | 26 | class CacheStoreClassDeclaration( 27 | private val irClassSymbol: IrClassSymbol, 28 | private val irBuiltIns: IrBuiltIns, 29 | ) { 30 | val irType: IrSimpleType 31 | get() = irClassSymbol.createType(false, emptyList()) 32 | 33 | private val irConstructorSymbol: IrConstructorSymbol 34 | get() = irClassSymbol.constructors.single { 35 | it.owner.valueParameters.size == 2 && 36 | it.owner.valueParameters[0].type == irBuiltIns.intType && 37 | it.owner.valueParameters[1].type == irBuiltIns.booleanType 38 | } 39 | 40 | private val irCacheOrInvokeFunctionSymbol: IrSimpleFunctionSymbol 41 | get() = irClassSymbol.functions 42 | .single { it.owner.name == cacheOrInvokedFunctionName } 43 | 44 | fun createConstructorCall( 45 | maxCountExpression: IrExpression?, 46 | lockExpression: IrExpression?, 47 | ): IrConstructorCall { 48 | val call = IrConstructorCallImpl( 49 | startOffset = UNDEFINED_OFFSET, 50 | endOffset = UNDEFINED_OFFSET, 51 | type = irType, 52 | symbol = irConstructorSymbol, 53 | typeArgumentsCount = 0, 54 | constructorTypeArgumentsCount = 0, 55 | valueArgumentsCount = 2, 56 | ) 57 | call.putValueArgument(0, maxCountExpression) 58 | call.putValueArgument(1, lockExpression) 59 | return call 60 | } 61 | 62 | fun createCacheOrInvokeFunctionCall( 63 | typeArgument: IrType, 64 | keyElements: List, 65 | blockExpression: IrExpression, 66 | dispatchReceiver: IrExpression? = null, 67 | ): IrCall { 68 | val call = IrCallImpl( 69 | startOffset = UNDEFINED_OFFSET, 70 | endOffset = UNDEFINED_OFFSET, 71 | type = typeArgument, 72 | symbol = irCacheOrInvokeFunctionSymbol, 73 | typeArgumentsCount = 1, 74 | valueArgumentsCount = 2, 75 | ) 76 | call.dispatchReceiver = dispatchReceiver 77 | val keyArgument = IrVarargImpl( 78 | startOffset = UNDEFINED_OFFSET, 79 | endOffset = UNDEFINED_OFFSET, 80 | type = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType), 81 | varargElementType = irBuiltIns.anyNType, 82 | elements = keyElements, 83 | ) 84 | call.putValueArgument(0, keyArgument) 85 | call.putValueArgument(1, blockExpression) 86 | call.putTypeArgument(0, typeArgument) 87 | return call 88 | } 89 | 90 | companion object { 91 | private val internalPackageName = FqName("com.moriatsushi.cacheable.internal") 92 | private val cacheStoreId = ClassId(internalPackageName, Name.identifier("CacheStore")) 93 | private val cacheOrInvokedFunctionName = Name.identifier("cacheOrInvoke") 94 | 95 | fun find(pluginContext: IrPluginContext): CacheStoreClassDeclaration? = 96 | pluginContext.referenceClass(cacheStoreId)?.let { 97 | CacheStoreClassDeclaration(it, pluginContext.irBuiltIns) 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/declaration/CacheableAnnotationDeclaration.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.compiler.declaration 2 | 3 | import org.jetbrains.kotlin.ir.backend.js.utils.valueArguments 4 | import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer 5 | import org.jetbrains.kotlin.ir.expressions.IrExpression 6 | import org.jetbrains.kotlin.ir.util.getAnnotation 7 | import org.jetbrains.kotlin.ir.util.hasAnnotation 8 | import org.jetbrains.kotlin.name.FqName 9 | 10 | class CacheableAnnotationDeclaration { 11 | fun hasAnnotation(annotationContainer: IrAnnotationContainer): Boolean = 12 | annotationContainer.hasAnnotation(name) 13 | 14 | fun findMaxCountExpression(annotationContainer: IrAnnotationContainer): IrExpression? = 15 | annotationContainer.getAnnotation(name) 16 | ?.valueArguments 17 | ?.getOrNull(0) 18 | 19 | fun findLockExpression(annotationContainer: IrAnnotationContainer): IrExpression? = 20 | annotationContainer.getAnnotation(name) 21 | ?.valueArguments 22 | ?.getOrNull(1) 23 | 24 | companion object { 25 | val name = FqName("com.moriatsushi.cacheable.Cacheable") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/declaration/CacheableDeclarations.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.compiler.declaration 2 | 3 | import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext 4 | 5 | class CacheableDeclarations( 6 | val cacheableAnnotationDeclaration: CacheableAnnotationDeclaration, 7 | val cacheStoreClassDeclaration: CacheStoreClassDeclaration, 8 | val coroutineCacheStoreClassDeclaration: CoroutineCacheStoreClassDeclaration, 9 | ) { 10 | companion object { 11 | fun find(pluginContext: IrPluginContext): CacheableDeclarations? { 12 | val cacheStoreClassDeclaration = 13 | CacheStoreClassDeclaration.find(pluginContext) ?: return null 14 | val coroutineCacheStoreClassDeclaration = 15 | CoroutineCacheStoreClassDeclaration.find(pluginContext) ?: return null 16 | 17 | return CacheableDeclarations( 18 | CacheableAnnotationDeclaration(), 19 | cacheStoreClassDeclaration, 20 | coroutineCacheStoreClassDeclaration, 21 | ) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/declaration/CoroutineCacheStoreClassDeclaration.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.compiler.declaration 2 | 3 | import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext 4 | import org.jetbrains.kotlin.ir.IrBuiltIns 5 | import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET 6 | import org.jetbrains.kotlin.ir.expressions.IrCall 7 | import org.jetbrains.kotlin.ir.expressions.IrConstructorCall 8 | import org.jetbrains.kotlin.ir.expressions.IrExpression 9 | import org.jetbrains.kotlin.ir.expressions.IrVarargElement 10 | import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl 11 | import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl 12 | import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl 13 | import org.jetbrains.kotlin.ir.symbols.IrClassSymbol 14 | import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol 15 | import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol 16 | import org.jetbrains.kotlin.ir.types.IrSimpleType 17 | import org.jetbrains.kotlin.ir.types.IrType 18 | import org.jetbrains.kotlin.ir.types.createType 19 | import org.jetbrains.kotlin.ir.types.typeWith 20 | import org.jetbrains.kotlin.ir.util.constructors 21 | import org.jetbrains.kotlin.ir.util.functions 22 | import org.jetbrains.kotlin.name.ClassId 23 | import org.jetbrains.kotlin.name.FqName 24 | import org.jetbrains.kotlin.name.Name 25 | 26 | class CoroutineCacheStoreClassDeclaration( 27 | private val irClassSymbol: IrClassSymbol, 28 | private val irBuiltIns: IrBuiltIns, 29 | ) { 30 | val irType: IrSimpleType 31 | get() = irClassSymbol.createType(false, emptyList()) 32 | 33 | private val irConstructorSymbol: IrConstructorSymbol 34 | get() = irClassSymbol.constructors.single { 35 | it.owner.valueParameters.size == 2 && 36 | it.owner.valueParameters[0].type == irBuiltIns.intType && 37 | it.owner.valueParameters[1].type == irBuiltIns.booleanType 38 | } 39 | 40 | private val irCacheOrInvokeFunctionSymbol: IrSimpleFunctionSymbol 41 | get() = irClassSymbol.functions 42 | .single { it.owner.name == cacheOrInvokedFunctionName } 43 | 44 | fun createConstructorCall( 45 | maxCountExpression: IrExpression?, 46 | lockExpression: IrExpression?, 47 | ): IrConstructorCall { 48 | val call = IrConstructorCallImpl( 49 | startOffset = UNDEFINED_OFFSET, 50 | endOffset = UNDEFINED_OFFSET, 51 | type = irType, 52 | symbol = irConstructorSymbol, 53 | typeArgumentsCount = 0, 54 | constructorTypeArgumentsCount = 0, 55 | valueArgumentsCount = 2, 56 | ) 57 | call.putValueArgument(0, maxCountExpression) 58 | call.putValueArgument(1, lockExpression) 59 | return call 60 | } 61 | 62 | fun createCacheOrInvokeFunctionCall( 63 | typeArgument: IrType, 64 | keyElements: List, 65 | blockExpression: IrExpression, 66 | dispatchReceiver: IrExpression? = null, 67 | ): IrCall { 68 | val call = IrCallImpl( 69 | startOffset = UNDEFINED_OFFSET, 70 | endOffset = UNDEFINED_OFFSET, 71 | type = typeArgument, 72 | symbol = irCacheOrInvokeFunctionSymbol, 73 | typeArgumentsCount = 1, 74 | valueArgumentsCount = 2, 75 | ) 76 | call.dispatchReceiver = dispatchReceiver 77 | val keyArgument = IrVarargImpl( 78 | startOffset = UNDEFINED_OFFSET, 79 | endOffset = UNDEFINED_OFFSET, 80 | type = irBuiltIns.arrayClass.typeWith(irBuiltIns.anyNType), 81 | varargElementType = irBuiltIns.anyNType, 82 | elements = keyElements, 83 | ) 84 | call.putValueArgument(0, keyArgument) 85 | call.putValueArgument(1, blockExpression) 86 | call.putTypeArgument(0, typeArgument) 87 | return call 88 | } 89 | 90 | companion object { 91 | private val internalPackageName = FqName("com.moriatsushi.cacheable.internal") 92 | private val cacheStoreId = 93 | ClassId(internalPackageName, Name.identifier("CoroutineCacheStore")) 94 | private val cacheOrInvokedFunctionName = Name.identifier("cacheOrInvoke") 95 | 96 | fun find(pluginContext: IrPluginContext): CoroutineCacheStoreClassDeclaration? = 97 | pluginContext.referenceClass(cacheStoreId)?.let { 98 | CoroutineCacheStoreClassDeclaration(it, pluginContext.irBuiltIns) 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/factory/IrActualFunctionFactory.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.compiler.factory 2 | 3 | import org.jetbrains.kotlin.backend.common.ir.moveBodyTo 4 | import org.jetbrains.kotlin.ir.builders.declarations.buildFun 5 | import org.jetbrains.kotlin.ir.declarations.IrFactory 6 | import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction 7 | import org.jetbrains.kotlin.ir.util.copyParameterDeclarationsFrom 8 | import org.jetbrains.kotlin.name.Name 9 | 10 | class IrActualFunctionFactory( 11 | private val irFactory: IrFactory, 12 | ) { 13 | fun create(originalFunction: IrSimpleFunction): IrSimpleFunction = 14 | originalFunction.renamed( 15 | Name.identifier(originalFunction.name.identifier + ACTUAL_SUFFIX), 16 | ) 17 | 18 | private fun IrSimpleFunction.renamed(name: Name): IrSimpleFunction { 19 | val original = this 20 | val copied = irFactory.buildFun { 21 | this.updateFrom(original) 22 | this.name = name 23 | this.returnType = original.returnType 24 | } 25 | copied.parent = original.parent 26 | copied.copyParameterDeclarationsFrom(original) 27 | copied.body = original.moveBodyTo(copied) 28 | return copied 29 | } 30 | 31 | companion object { 32 | private const val ACTUAL_SUFFIX = "\$actual" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/factory/IrCacheStoreFieldFactory.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.compiler.factory 2 | 3 | import com.moriatsushi.cacheable.compiler.declaration.CacheableDeclarations 4 | import org.jetbrains.kotlin.descriptors.DescriptorVisibilities 5 | import org.jetbrains.kotlin.ir.builders.declarations.buildField 6 | import org.jetbrains.kotlin.ir.declarations.IrFactory 7 | import org.jetbrains.kotlin.ir.declarations.IrField 8 | import org.jetbrains.kotlin.ir.declarations.IrFunction 9 | import org.jetbrains.kotlin.ir.declarations.createExpressionBody 10 | import org.jetbrains.kotlin.ir.util.isSuspend 11 | import org.jetbrains.kotlin.ir.util.isTopLevel 12 | import org.jetbrains.kotlin.name.Name 13 | 14 | class IrCacheStoreFieldFactory( 15 | private val irFactory: IrFactory, 16 | private val cacheableDeclarations: CacheableDeclarations, 17 | ) { 18 | fun create(function: IrFunction): IrField { 19 | val field = irFactory.buildField { 20 | name = Name.identifier(function.name.identifier + CACHE_STORE_SUFFIX) 21 | type = if (function.isSuspend) { 22 | cacheableDeclarations.coroutineCacheStoreClassDeclaration.irType 23 | } else { 24 | cacheableDeclarations.cacheStoreClassDeclaration.irType 25 | } 26 | visibility = DescriptorVisibilities.PRIVATE 27 | isStatic = function.isTopLevel 28 | } 29 | val maxCountExpression = cacheableDeclarations.cacheableAnnotationDeclaration 30 | .findMaxCountExpression(function) 31 | val lockExpression = cacheableDeclarations.cacheableAnnotationDeclaration 32 | .findLockExpression(function) 33 | val constructorCall = if (function.isSuspend) { 34 | cacheableDeclarations.coroutineCacheStoreClassDeclaration 35 | .createConstructorCall(maxCountExpression, lockExpression) 36 | } else { 37 | cacheableDeclarations.cacheStoreClassDeclaration 38 | .createConstructorCall(maxCountExpression, lockExpression) 39 | } 40 | field.initializer = irFactory.createExpressionBody(constructorCall) 41 | field.parent = function.parent 42 | return field 43 | } 44 | 45 | companion object { 46 | private const val CACHE_STORE_SUFFIX = "\$cacheStore" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /cacheable-compiler/src/main/kotlin/com/moriatsushi/cacheable/compiler/factory/IrCacheableFunctionBodyFactory.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.compiler.factory 2 | 3 | import com.moriatsushi.cacheable.compiler.declaration.CacheableDeclarations 4 | import org.jetbrains.kotlin.descriptors.DescriptorVisibilities 5 | import org.jetbrains.kotlin.ir.IrBuiltIns 6 | import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET 7 | import org.jetbrains.kotlin.ir.builders.declarations.buildFun 8 | import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin 9 | import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent 10 | import org.jetbrains.kotlin.ir.declarations.IrFactory 11 | import org.jetbrains.kotlin.ir.declarations.IrField 12 | import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction 13 | import org.jetbrains.kotlin.ir.declarations.IrValueParameter 14 | import org.jetbrains.kotlin.ir.declarations.createBlockBody 15 | import org.jetbrains.kotlin.ir.expressions.IrBlockBody 16 | import org.jetbrains.kotlin.ir.expressions.IrBody 17 | import org.jetbrains.kotlin.ir.expressions.IrCall 18 | import org.jetbrains.kotlin.ir.expressions.IrExpression 19 | import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression 20 | import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin 21 | import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl 22 | import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionExpressionImpl 23 | import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl 24 | import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl 25 | import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl 26 | import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol 27 | import org.jetbrains.kotlin.ir.types.IrType 28 | import org.jetbrains.kotlin.ir.types.typeWith 29 | import org.jetbrains.kotlin.ir.util.isSuspend 30 | import org.jetbrains.kotlin.name.SpecialNames 31 | 32 | class IrCacheableFunctionBodyFactory( 33 | private val irBuiltIns: IrBuiltIns, 34 | private val irFactory: IrFactory, 35 | private val cacheableDeclarations: CacheableDeclarations, 36 | ) { 37 | fun create( 38 | originalFunction: IrSimpleFunction, 39 | actualFunction: IrSimpleFunction, 40 | cacheStoreField: IrField, 41 | ): IrBody { 42 | val thisReceiver = originalFunction.dispatchReceiverParameter?.let { 43 | IrGetValueImpl( 44 | startOffset = UNDEFINED_OFFSET, 45 | endOffset = UNDEFINED_OFFSET, 46 | symbol = it.symbol, 47 | type = it.type, 48 | ) 49 | } 50 | val actualCall = createActualCall( 51 | actualFunction = actualFunction, 52 | valueParameters = originalFunction.valueParameters, 53 | thisReceiver = thisReceiver, 54 | ) 55 | val lambdaExpression = createLambdaExpression( 56 | actualCall = actualCall, 57 | parent = originalFunction, 58 | ) 59 | val cacheStoreCall = createCacheStoreCall( 60 | cacheStoreField = cacheStoreField, 61 | valueParameters = originalFunction.valueParameters, 62 | lambdaExpression = lambdaExpression, 63 | thisReceiver = thisReceiver, 64 | typeArgument = originalFunction.returnType, 65 | isSuspend = originalFunction.isSuspend, 66 | ) 67 | return createSingleLineBlockBody( 68 | type = originalFunction.returnType, 69 | returnTargetSymbol = originalFunction.symbol, 70 | value = cacheStoreCall, 71 | ) 72 | } 73 | 74 | private fun createActualCall( 75 | actualFunction: IrSimpleFunction, 76 | valueParameters: List, 77 | thisReceiver: IrExpression?, 78 | ): IrCall { 79 | assert(valueParameters.size == actualFunction.valueParameters.size) 80 | val actualCall = IrCallImpl( 81 | startOffset = UNDEFINED_OFFSET, 82 | endOffset = UNDEFINED_OFFSET, 83 | type = actualFunction.returnType, 84 | symbol = actualFunction.symbol, 85 | typeArgumentsCount = 0, 86 | valueArgumentsCount = actualFunction.valueParameters.size, 87 | ) 88 | actualCall.dispatchReceiver = thisReceiver 89 | for (valueParameter in valueParameters) { 90 | val argument = IrGetValueImpl( 91 | startOffset = UNDEFINED_OFFSET, 92 | endOffset = UNDEFINED_OFFSET, 93 | symbol = valueParameter.symbol, 94 | type = valueParameter.type, 95 | ) 96 | actualCall.putValueArgument(valueParameter.index, argument) 97 | } 98 | return actualCall 99 | } 100 | 101 | private fun createLambdaExpression( 102 | actualCall: IrCall, 103 | parent: IrDeclarationParent, 104 | ): IrFunctionExpression { 105 | val lambda = irFactory.buildFun { 106 | origin = IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA 107 | name = SpecialNames.ANONYMOUS 108 | returnType = actualCall.type 109 | visibility = DescriptorVisibilities.LOCAL 110 | isSuspend = actualCall.isSuspend 111 | } 112 | lambda.parent = parent 113 | lambda.body = createSingleLineBlockBody( 114 | type = actualCall.type, 115 | returnTargetSymbol = lambda.symbol, 116 | value = actualCall, 117 | ) 118 | val lambdaType = if (actualCall.isSuspend) { 119 | irBuiltIns.suspendFunctionN(0) 120 | } else { 121 | irBuiltIns.functionN(0) 122 | }.typeWith(listOf(actualCall.type)) 123 | 124 | return IrFunctionExpressionImpl( 125 | startOffset = UNDEFINED_OFFSET, 126 | endOffset = UNDEFINED_OFFSET, 127 | type = lambdaType, 128 | function = lambda, 129 | origin = IrStatementOrigin.LAMBDA, 130 | ) 131 | } 132 | 133 | private fun createCacheStoreCall( 134 | cacheStoreField: IrField, 135 | valueParameters: List, 136 | lambdaExpression: IrExpression, 137 | thisReceiver: IrExpression?, 138 | typeArgument: IrType, 139 | isSuspend: Boolean, 140 | ): IrCall { 141 | val dispatchReceiver = IrGetFieldImpl( 142 | startOffset = UNDEFINED_OFFSET, 143 | endOffset = UNDEFINED_OFFSET, 144 | symbol = cacheStoreField.symbol, 145 | type = cacheStoreField.type, 146 | ) 147 | dispatchReceiver.receiver = thisReceiver 148 | val keyElements = valueParameters.map { 149 | IrGetValueImpl( 150 | startOffset = UNDEFINED_OFFSET, 151 | endOffset = UNDEFINED_OFFSET, 152 | symbol = it.symbol, 153 | type = it.type, 154 | ) 155 | } 156 | return if (isSuspend) { 157 | cacheableDeclarations.coroutineCacheStoreClassDeclaration 158 | .createCacheOrInvokeFunctionCall( 159 | typeArgument = typeArgument, 160 | keyElements = keyElements, 161 | blockExpression = lambdaExpression, 162 | dispatchReceiver = dispatchReceiver, 163 | ) 164 | } else { 165 | cacheableDeclarations.cacheStoreClassDeclaration 166 | .createCacheOrInvokeFunctionCall( 167 | typeArgument = typeArgument, 168 | keyElements = keyElements, 169 | blockExpression = lambdaExpression, 170 | dispatchReceiver = dispatchReceiver, 171 | ) 172 | } 173 | } 174 | 175 | private fun createSingleLineBlockBody( 176 | type: IrType, 177 | returnTargetSymbol: IrReturnTargetSymbol, 178 | value: IrExpression, 179 | ): IrBlockBody = irFactory.createBlockBody( 180 | startOffset = UNDEFINED_OFFSET, 181 | endOffset = UNDEFINED_OFFSET, 182 | listOf( 183 | IrReturnImpl( 184 | startOffset = UNDEFINED_OFFSET, 185 | endOffset = UNDEFINED_OFFSET, 186 | type = type, 187 | returnTargetSymbol = returnTargetSymbol, 188 | value = value, 189 | ), 190 | ), 191 | ) 192 | } 193 | -------------------------------------------------------------------------------- /cacheable-core/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.kotlin.multiplatform) 3 | alias(libs.plugins.maven.publish) 4 | alias(libs.plugins.kotlinx.atomicfu) 5 | } 6 | 7 | kotlin { 8 | jvm() 9 | js(IR) { 10 | nodejs() 11 | browser() 12 | } 13 | iosX64() 14 | iosArm64() 15 | iosSimulatorArm64() 16 | macosX64() 17 | macosArm64() 18 | watchosArm64() 19 | watchosX64() 20 | watchosSimulatorArm64() 21 | watchosDeviceArm64() 22 | tvosArm64() 23 | tvosX64() 24 | tvosSimulatorArm64() 25 | 26 | mingwX64() 27 | linuxX64() 28 | linuxArm64() 29 | 30 | sourceSets { 31 | val commonMain by getting { 32 | dependencies { 33 | implementation(libs.stately.concurrent.collections) 34 | implementation(libs.kotlinx.coroutines.core) 35 | implementation(libs.kotlinx.datetime) 36 | } 37 | } 38 | 39 | val commonTest by getting { 40 | dependencies { 41 | implementation(kotlin("test")) 42 | implementation(libs.kotlinx.coroutines.test) 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /cacheable-core/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=cacheable-core 2 | POM_NAME=Kotlin Cacheable 3 | POM_DESCRIPTION=An annotation-based caching library for Kotlin Multiplatform 4 | POM_PACKAGING=jar 5 | -------------------------------------------------------------------------------- /cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/Cacheable.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable 2 | 3 | /** 4 | * An annotation for caching the result of a function. When you call a function annotated with this, 5 | * the function will not be invoked and the cached value will be returned if the function has been 6 | * called before with the same arguments. When a cacheable function is in a class, the cache is only 7 | * shared within the instance of the class. 8 | * 9 | * @param maxCount The maximum number of caches. If the number of caches exceeds this value, the 10 | * last used cache will be deleted. The default value is [unlimited][UNLIMITED_CACHE_COUNT]. 11 | * @param lock When this is true, the function is guaranteed to be called only once even if the 12 | * function is called multiple times with the same arguments at the same time. Otherwise, the 13 | * function may be called multiple times with the same arguments at the same time. The default value 14 | * is false. 15 | */ 16 | @Target(AnnotationTarget.FUNCTION) 17 | @Retention(AnnotationRetention.SOURCE) 18 | @MustBeDocumented 19 | annotation class Cacheable( 20 | val maxCount: Int = UNLIMITED_CACHE_COUNT, 21 | val lock: Boolean = false, 22 | ) 23 | 24 | /** 25 | * A constant indicating that the number of caches is unlimited. 26 | */ 27 | const val UNLIMITED_CACHE_COUNT = -1 28 | -------------------------------------------------------------------------------- /cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/CacheableConfiguration.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable 2 | 3 | import com.moriatsushi.cacheable.internal.DefaultTimeProvider 4 | 5 | /** 6 | * An object that holds the configuration of the cacheable library. 7 | */ 8 | object CacheableConfiguration { 9 | /** 10 | * A current time provider that is used to record the last access time of the cache. 11 | */ 12 | var timeProvider: CacheableTimeProvider = DefaultTimeProvider 13 | 14 | /** 15 | * Resets the [timeProvider] to the default. 16 | */ 17 | fun resetTimeProvider() { 18 | timeProvider = DefaultTimeProvider 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/CacheableTimeProvider.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable 2 | 3 | /** 4 | * An interface that provides the current epoch milliseconds. 5 | */ 6 | interface CacheableTimeProvider { 7 | val currentEpochMillis: Long 8 | } 9 | -------------------------------------------------------------------------------- /cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/internal/BaseCacheStore.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.internal 2 | 3 | import co.touchlab.stately.collections.ConcurrentMutableMap 4 | import com.moriatsushi.cacheable.CacheableConfiguration 5 | import com.moriatsushi.cacheable.UNLIMITED_CACHE_COUNT 6 | 7 | /** 8 | * A base cache store. 9 | */ 10 | internal class BaseCacheStore( 11 | private val maxCount: Int, 12 | private val currentEpochMillis: () -> Long, 13 | ) { 14 | private val cacheMap = ConcurrentMutableMap() 15 | 16 | constructor(maxCount: Int = UNLIMITED_CACHE_COUNT) : this( 17 | maxCount, 18 | { CacheableConfiguration.timeProvider.currentEpochMillis }, 19 | ) 20 | 21 | inline fun cacheOrInvoke(key: Any, value: () -> T): T { 22 | val cacheEntry = getCacheEntry(key) 23 | if (cacheEntry != null) { 24 | @Suppress("UNCHECKED_CAST") 25 | return cacheEntry.value as T 26 | } 27 | 28 | val newValue = value() 29 | saveCacheEntry(key, newValue) 30 | return newValue 31 | } 32 | 33 | private fun getCacheEntry(key: Any): CacheEntry? = 34 | cacheMap.block { map -> 35 | val entry = map[key] 36 | if (entry != null) { 37 | entry.lastAccessedEpochMillis = currentEpochMillis() 38 | } 39 | entry 40 | } 41 | 42 | private fun saveCacheEntry(key: Any, value: Any?) { 43 | cacheMap.block { map -> 44 | if (maxCount != UNLIMITED_CACHE_COUNT && map.size >= maxCount) { 45 | val oldestEntry = map.minByOrNull { it.value.lastAccessedEpochMillis } 46 | if (oldestEntry != null) { 47 | map.remove(oldestEntry.key) 48 | } 49 | } 50 | 51 | map[key] = CacheEntry(value, currentEpochMillis()) 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/internal/CacheEntry.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.internal 2 | 3 | internal data class CacheEntry( 4 | val value: Any?, 5 | var lastAccessedEpochMillis: Long, 6 | ) 7 | -------------------------------------------------------------------------------- /cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/internal/CacheStore.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.internal 2 | 3 | import com.moriatsushi.cacheable.UNLIMITED_CACHE_COUNT 4 | import kotlinx.atomicfu.locks.SynchronizedObject 5 | import kotlinx.atomicfu.locks.synchronized 6 | 7 | /** 8 | * A cache store for a non-suspend function. 9 | */ 10 | internal class CacheStore( 11 | private val cacheStore: BaseCacheStore = BaseCacheStore(), 12 | private val lockStore: LockStore = 13 | LockStore.createSynchronizedObjectStore(), 14 | private val lock: Boolean = false, 15 | ) { 16 | constructor( 17 | maxCount: Int = UNLIMITED_CACHE_COUNT, 18 | lock: Boolean = false, 19 | ) : this(BaseCacheStore(maxCount), lock = lock) 20 | 21 | inline fun cacheOrInvoke(vararg key: Any?, value: () -> T): T { 22 | val keyList = key.toList() 23 | return if (lock) { 24 | withLock(keyList) { 25 | cacheStore.cacheOrInvoke(keyList, value = value) 26 | } 27 | } else { 28 | cacheStore.cacheOrInvoke(keyList, value = value) 29 | } 30 | } 31 | 32 | private inline fun withLock(key: Any, block: () -> T): T { 33 | val lockKey = lockStore.getLockKey(key) 34 | return synchronized(lockKey) { 35 | try { 36 | block() 37 | } finally { 38 | lockStore.removeLockKey(key) 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/internal/CoroutineCacheStore.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.internal 2 | 3 | import com.moriatsushi.cacheable.UNLIMITED_CACHE_COUNT 4 | import kotlinx.coroutines.sync.Mutex 5 | import kotlinx.coroutines.sync.withLock 6 | 7 | /** 8 | * A cache store for a suspend function. 9 | */ 10 | internal class CoroutineCacheStore( 11 | private val cacheStore: BaseCacheStore = BaseCacheStore(), 12 | private val lockStore: LockStore = LockStore.createMutexStore(), 13 | private val lock: Boolean = false, 14 | ) { 15 | constructor( 16 | maxCount: Int = UNLIMITED_CACHE_COUNT, 17 | lock: Boolean = false, 18 | ) : this(BaseCacheStore(maxCount), lock = lock) 19 | 20 | @Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE") 21 | suspend inline fun cacheOrInvoke(vararg key: Any?, value: suspend () -> T): T { 22 | val keyList = key.toList() 23 | return if (lock) { 24 | withLock(keyList) { 25 | cacheStore.cacheOrInvoke(keyList) { value() } 26 | } 27 | } else { 28 | cacheStore.cacheOrInvoke(keyList) { value() } 29 | } 30 | } 31 | 32 | private suspend inline fun withLock(key: Any, block: () -> T): T { 33 | val mutex = lockStore.getLockKey(key) 34 | return mutex.withLock { 35 | try { 36 | block() 37 | } finally { 38 | lockStore.removeLockKey(key) 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/internal/DefaultTimeProvider.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.internal 2 | 3 | import com.moriatsushi.cacheable.CacheableTimeProvider 4 | import kotlinx.datetime.Clock 5 | 6 | internal object DefaultTimeProvider : CacheableTimeProvider { 7 | override val currentEpochMillis: Long 8 | get() = Clock.System.now().toEpochMilliseconds() 9 | } 10 | -------------------------------------------------------------------------------- /cacheable-core/src/commonMain/kotlin/com/moriatsushi/cacheable/internal/LockStore.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.internal 2 | 3 | import co.touchlab.stately.collections.ConcurrentMutableMap 4 | import kotlinx.atomicfu.locks.SynchronizedObject 5 | import kotlinx.coroutines.sync.Mutex 6 | 7 | internal class LockStore(private val lockFactory: () -> T) { 8 | private val lockMap = ConcurrentMutableMap>() 9 | 10 | fun getLockKey(key: Any): T = 11 | lockMap.block { 12 | val entry = lockMap.getOrPut(key) { Entry(lockFactory()) } 13 | entry.referrerCount++ 14 | entry.lock 15 | } 16 | 17 | fun removeLockKey(key: Any) { 18 | lockMap.block { 19 | val entry = lockMap[key] ?: return@block 20 | entry.referrerCount-- 21 | if (entry.referrerCount <= 0) { 22 | lockMap.remove(key) 23 | } 24 | } 25 | } 26 | 27 | private data class Entry(val lock: T, var referrerCount: Int = 0) 28 | 29 | companion object { 30 | fun createSynchronizedObjectStore(): LockStore = 31 | LockStore(::SynchronizedObject) 32 | 33 | fun createMutexStore(): LockStore = LockStore(::Mutex) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /cacheable-core/src/commonTest/kotlin/com/moriatsushi/cacheable/internal/CacheStoreTest.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.internal 2 | 3 | import kotlin.test.Test 4 | import kotlin.test.assertEquals 5 | 6 | class CacheStoreTest { 7 | @Test 8 | fun testCacheOrInvoke() { 9 | val cacheStore = CacheStore() 10 | val result1 = cacheStore.cacheOrInvoke { "value1" } 11 | assertEquals("value1", result1) 12 | 13 | val result2 = cacheStore.cacheOrInvoke { "value2" } 14 | assertEquals("value1", result2) 15 | } 16 | 17 | @Test 18 | fun testCacheOrInvoke_withKey() { 19 | val cacheStore = CacheStore() 20 | val result1 = cacheStore.cacheOrInvoke("key1") { "value1" } 21 | assertEquals("value1", result1) 22 | 23 | val result2 = cacheStore.cacheOrInvoke("key2") { "value2" } 24 | assertEquals("value2", result2) 25 | 26 | val result3 = cacheStore.cacheOrInvoke("key1") { "value3" } 27 | assertEquals("value1", result3) 28 | 29 | val result4 = cacheStore.cacheOrInvoke("key2") { "value4" } 30 | assertEquals("value2", result4) 31 | } 32 | 33 | @Test 34 | fun testCacheOrInvoke_cacheNull() { 35 | val cacheStore = CacheStore() 36 | val result1 = cacheStore.cacheOrInvoke { null } 37 | assertEquals(null, result1) 38 | 39 | val result2 = cacheStore.cacheOrInvoke { "value" } 40 | assertEquals(null, result2) 41 | } 42 | 43 | @Test 44 | fun testCacheOrInvoke_withMaxCount() { 45 | var currentEpochMillis: Long = 0 46 | val cacheStore = CacheStore(BaseCacheStore(maxCount = 2) { currentEpochMillis }) 47 | 48 | currentEpochMillis = 0 49 | cacheStore.cacheOrInvoke("key1") { "value1" } 50 | currentEpochMillis = 1 51 | cacheStore.cacheOrInvoke("key2") { "value2" } 52 | currentEpochMillis = 2 53 | cacheStore.cacheOrInvoke("key1") { "value3" } 54 | currentEpochMillis = 3 55 | cacheStore.cacheOrInvoke("key3") { "value4" } 56 | 57 | currentEpochMillis = 4 58 | val result1 = cacheStore.cacheOrInvoke("key1") { "value5" } 59 | assertEquals("value1", result1) 60 | 61 | currentEpochMillis = 5 62 | val result2 = cacheStore.cacheOrInvoke("key2") { "value6" } 63 | assertEquals("value6", result2) 64 | 65 | currentEpochMillis = 6 66 | val result3 = cacheStore.cacheOrInvoke("key3") { "value7" } 67 | assertEquals("value7", result3) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /cacheable-core/src/commonTest/kotlin/com/moriatsushi/cacheable/internal/CoroutineCacheStoreTest.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.internal 2 | 3 | import kotlin.test.Test 4 | import kotlin.test.assertEquals 5 | import kotlinx.coroutines.delay 6 | import kotlinx.coroutines.launch 7 | import kotlinx.coroutines.test.runTest 8 | 9 | class CoroutineCacheStoreTest { 10 | @Test 11 | fun testCacheOrInvoke_withLock() = runTest { 12 | val cacheStore = CoroutineCacheStore(lock = true) 13 | 14 | launch { 15 | val result1 = cacheStore.cacheOrInvoke { 16 | delay(100) 17 | "value1" 18 | } 19 | assertEquals("value1", result1) 20 | } 21 | launch { 22 | val result2 = cacheStore.cacheOrInvoke { 23 | delay(100) 24 | "value2" 25 | } 26 | assertEquals("value1", result2) 27 | } 28 | } 29 | 30 | @Test 31 | fun testCacheOrInvoke_withoutLock() = runTest { 32 | val cacheStore = CoroutineCacheStore(lock = false) 33 | 34 | launch { 35 | val result1 = cacheStore.cacheOrInvoke { 36 | delay(100) 37 | "value1" 38 | } 39 | assertEquals("value1", result1) 40 | } 41 | launch { 42 | val result2 = cacheStore.cacheOrInvoke { 43 | delay(100) 44 | "value2" 45 | } 46 | assertEquals("value2", result2) 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cacheable-core/src/commonTest/kotlin/com/moriatsushi/cacheable/internal/LockStoreTest.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.internal 2 | 3 | import kotlin.test.Test 4 | import kotlin.test.assertEquals 5 | import kotlin.test.assertNotEquals 6 | 7 | class LockStoreTest { 8 | @Test 9 | fun testGetLockKey_sameKeys() { 10 | val lockStore = LockStore.createSynchronizedObjectStore() 11 | 12 | val result1 = lockStore.getLockKey("key1") 13 | val result2 = lockStore.getLockKey("key1") 14 | assertEquals(result1, result2) 15 | } 16 | 17 | @Test 18 | fun testTetLockKey_differentKeys() { 19 | val lockStore = LockStore.createSynchronizedObjectStore() 20 | 21 | val result1 = lockStore.getLockKey("key1") 22 | val result2 = lockStore.getLockKey("key2") 23 | assertNotEquals(result1, result2) 24 | } 25 | 26 | @Test 27 | fun testRemoveLockKey() { 28 | val lockStore = LockStore.createSynchronizedObjectStore() 29 | 30 | val result1 = lockStore.getLockKey("key1") 31 | val result2 = lockStore.getLockKey("key1") 32 | lockStore.removeLockKey("key1") 33 | lockStore.removeLockKey("key1") 34 | 35 | val result3 = lockStore.getLockKey("key1") 36 | assertEquals(result1, result2) 37 | assertNotEquals(result1, result3) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cacheable-gradle-plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `java-gradle-plugin` 3 | kotlin("jvm") 4 | alias(libs.plugins.maven.publish) 5 | } 6 | 7 | dependencies { 8 | implementation(kotlin("gradle-plugin-api")) 9 | } 10 | 11 | gradlePlugin { 12 | plugins { 13 | create("cacheable") { 14 | id = "com.moriatsushi.cacheable" 15 | implementationClass = 16 | "com.moriatsushi.cacheable.gradle.plugin.CacheableCompilerPluginSupportPlugin" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /cacheable-gradle-plugin/gradle.properties: -------------------------------------------------------------------------------- 1 | POM_ARTIFACT_ID=cacheable-gradle-plugin 2 | POM_NAME=Kotlin Cacheable 3 | POM_DESCRIPTION=An annotation-based caching library for Kotlin Multiplatform 4 | POM_PACKAGING=jar 5 | -------------------------------------------------------------------------------- /cacheable-gradle-plugin/src/main/kotlin/com/moriatsushi/cacheable/gradle/plugin/CacheableCompilerPluginSupportPlugin.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.gradle.plugin 2 | 3 | import org.gradle.api.provider.Provider 4 | import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation 5 | import org.jetbrains.kotlin.gradle.plugin.KotlinCompilerPluginSupportPlugin 6 | import org.jetbrains.kotlin.gradle.plugin.SubpluginArtifact 7 | import org.jetbrains.kotlin.gradle.plugin.SubpluginOption 8 | 9 | class CacheableCompilerPluginSupportPlugin : KotlinCompilerPluginSupportPlugin { 10 | override fun applyToCompilation( 11 | kotlinCompilation: KotlinCompilation<*>, 12 | ): Provider> = 13 | kotlinCompilation.target.project.provider { emptyList() } 14 | 15 | override fun getCompilerPluginId(): String = "com.moriatsushi.cacheable.compiler" 16 | 17 | override fun getPluginArtifact(): SubpluginArtifact = SubpluginArtifact( 18 | groupId = "com.moriatsushi.cacheable", 19 | artifactId = "cacheable-compiler", 20 | version = "0.0.3", 21 | ) 22 | 23 | override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean = true 24 | } 25 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 2 | org.gradle.parallel=true 3 | org.gradle.caching=true 4 | 5 | # Kotlin 6 | kotlin.code.style=official 7 | kotlin.mpp.androidSourceSetLayoutVersion=2 8 | 9 | # Maven Central 10 | SONATYPE_HOST=S01 11 | RELEASE_SIGNING_ENABLED=false 12 | GROUP=com.moriatsushi.cacheable 13 | VERSION_NAME=0.0.3 14 | 15 | POM_NAME=Kotlin Cacheable 16 | POM_DESCRIPTION=An annotation-based cache library for Kotlin Multiplatform. 17 | POM_INCEPTION_YEAR=2023 18 | POM_URL=https://github.com/mori-atsushi/kotlin-cacheable 19 | 20 | POM_LICENSE_NAME=The Apache Software License, Version 2.0 21 | POM_LICENSE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt 22 | POM_LICENSE_DIST=repo 23 | 24 | POM_SCM_URL=https://github.com/mori-atsushi/kotlin-cacheable 25 | POM_SCM_CONNECTION=scm:git:https://github.com/mori-atsushi/kotlin-cacheable 26 | POM_SCM_DEV_CONNECTION=scm:git:https://github.com/mori-atsushi/kotlin-cacheable 27 | 28 | POM_DEVELOPER_ID=moriatsushi 29 | POM_DEVELOPER_NAME=Mori Atsushi 30 | POM_DEVELOPER_URL=https://github.com/mori-atsushi/ 31 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | auto-service = "1.1.1" 3 | auto-service-ksp = "1.1.0" 4 | kotlin = "1.9.22" 5 | ktlint = "0.48.1" 6 | maven-publish = "0.27.0" 7 | spotless = "6.23.3" 8 | stately = "2.0.6" 9 | kotlinx-atomicfu = "0.22.0" 10 | kotlinx-coroutines = "1.7.3" 11 | kotlinx-datetime = "0.5.0" 12 | ksp = "1.9.22-1.0.16" 13 | 14 | [libraries] 15 | auto-service-annotations = { module = "com.google.auto.service:auto-service-annotations", version.ref = "auto-service" } 16 | auto-service-ksp = { module = "dev.zacsweers.autoservice:auto-service-ksp", version.ref = "auto-service-ksp" } 17 | stately-concurrent-collections = { module = "co.touchlab:stately-concurrent-collections", version.ref = "stately" } 18 | kotlin-compiler-embeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "kotlin" } 19 | kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } 20 | kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" } 21 | kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinx-datetime" } 22 | 23 | [plugins] 24 | kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } 25 | kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } 26 | kotlinx-atomicfu = { id = "kotlinx-atomicfu", version.ref = "kotlinx-atomicfu" } 27 | ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } 28 | maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "maven-publish" } 29 | spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } 30 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mori-atsushi/kotlin-cacheable/fe25a47fd6194fe33d928fbafef38a44feac6353/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 87 | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit 88 | 89 | # Use the maximum available, or set MAX_FD != -1 to use that value. 90 | MAX_FD=maximum 91 | 92 | warn () { 93 | echo "$*" 94 | } >&2 95 | 96 | die () { 97 | echo 98 | echo "$*" 99 | echo 100 | exit 1 101 | } >&2 102 | 103 | # OS specific support (must be 'true' or 'false'). 104 | cygwin=false 105 | msys=false 106 | darwin=false 107 | nonstop=false 108 | case "$( uname )" in #( 109 | CYGWIN* ) cygwin=true ;; #( 110 | Darwin* ) darwin=true ;; #( 111 | MSYS* | MINGW* ) msys=true ;; #( 112 | NONSTOP* ) nonstop=true ;; 113 | esac 114 | 115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 116 | 117 | 118 | # Determine the Java command to use to start the JVM. 119 | if [ -n "$JAVA_HOME" ] ; then 120 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 121 | # IBM's JDK on AIX uses strange locations for the executables 122 | JAVACMD=$JAVA_HOME/jre/sh/java 123 | else 124 | JAVACMD=$JAVA_HOME/bin/java 125 | fi 126 | if [ ! -x "$JAVACMD" ] ; then 127 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 128 | 129 | Please set the JAVA_HOME variable in your environment to match the 130 | location of your Java installation." 131 | fi 132 | else 133 | JAVACMD=java 134 | if ! command -v java >/dev/null 2>&1 135 | then 136 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | fi 142 | 143 | # Increase the maximum file descriptors if we can. 144 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 145 | case $MAX_FD in #( 146 | max*) 147 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 148 | # shellcheck disable=SC2039,SC3045 149 | MAX_FD=$( ulimit -H -n ) || 150 | warn "Could not query maximum file descriptor limit" 151 | esac 152 | case $MAX_FD in #( 153 | '' | soft) :;; #( 154 | *) 155 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 156 | # shellcheck disable=SC2039,SC3045 157 | ulimit -n "$MAX_FD" || 158 | warn "Could not set maximum file descriptor limit to $MAX_FD" 159 | esac 160 | fi 161 | 162 | # Collect all arguments for the java command, stacking in reverse order: 163 | # * args from the command line 164 | # * the main class name 165 | # * -classpath 166 | # * -D...appname settings 167 | # * --module-path (only if needed) 168 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 169 | 170 | # For Cygwin or MSYS, switch paths to Windows format before running java 171 | if "$cygwin" || "$msys" ; then 172 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 173 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 174 | 175 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 176 | 177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 178 | for arg do 179 | if 180 | case $arg in #( 181 | -*) false ;; # don't mess with options #( 182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 183 | [ -e "$t" ] ;; #( 184 | *) false ;; 185 | esac 186 | then 187 | arg=$( cygpath --path --ignore --mixed "$arg" ) 188 | fi 189 | # Roll the args list around exactly as many times as the number of 190 | # args, so each arg winds up back in the position where it started, but 191 | # possibly modified. 192 | # 193 | # NB: a `for` loop captures its iteration list before it begins, so 194 | # changing the positional parameters here affects neither the number of 195 | # iterations, nor the values presented in `arg`. 196 | shift # remove old arg 197 | set -- "$@" "$arg" # push replacement arg 198 | done 199 | fi 200 | 201 | 202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 204 | 205 | # Collect all arguments for the java command: 206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 207 | # and any embedded shellness will be escaped. 208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 209 | # treated as '${Hostname}' itself on the command line. 210 | 211 | set -- \ 212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 213 | -classpath "$CLASSPATH" \ 214 | org.gradle.wrapper.GradleWrapperMain \ 215 | "$@" 216 | 217 | # Stop when "xargs" is not available. 218 | if ! command -v xargs >/dev/null 2>&1 219 | then 220 | die "xargs is not available" 221 | fi 222 | 223 | # Use "xargs" to parse quoted args. 224 | # 225 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 226 | # 227 | # In Bash we could simply go: 228 | # 229 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 230 | # set -- "${ARGS[@]}" "$@" 231 | # 232 | # but POSIX shell has neither arrays nor command substitution, so instead we 233 | # post-process each arg (as a line of input to sed) to backslash-escape any 234 | # character that might be a shell metacharacter, then use eval to reverse 235 | # that process (while maintaining the separation between arguments), and wrap 236 | # the whole thing up as a single "set" statement. 237 | # 238 | # This will of course break if any of these variables contains a newline or 239 | # an unmatched quote. 240 | # 241 | 242 | eval "set -- $( 243 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 244 | xargs -n1 | 245 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 246 | tr '\n' ' ' 247 | )" '"$@"' 248 | 249 | exec "$JAVACMD" "$@" 250 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /kotlin-js-store/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@colors/colors@1.5.0": 6 | version "1.5.0" 7 | resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" 8 | integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== 9 | 10 | "@discoveryjs/json-ext@^0.5.0": 11 | version "0.5.7" 12 | resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" 13 | integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== 14 | 15 | "@jridgewell/gen-mapping@^0.3.0": 16 | version "0.3.3" 17 | resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" 18 | integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== 19 | dependencies: 20 | "@jridgewell/set-array" "^1.0.1" 21 | "@jridgewell/sourcemap-codec" "^1.4.10" 22 | "@jridgewell/trace-mapping" "^0.3.9" 23 | 24 | "@jridgewell/resolve-uri@^3.1.0": 25 | version "3.1.1" 26 | resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" 27 | integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== 28 | 29 | "@jridgewell/set-array@^1.0.1": 30 | version "1.1.2" 31 | resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" 32 | integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== 33 | 34 | "@jridgewell/source-map@^0.3.3": 35 | version "0.3.5" 36 | resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" 37 | integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== 38 | dependencies: 39 | "@jridgewell/gen-mapping" "^0.3.0" 40 | "@jridgewell/trace-mapping" "^0.3.9" 41 | 42 | "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": 43 | version "1.4.15" 44 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" 45 | integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== 46 | 47 | "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": 48 | version "0.3.20" 49 | resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" 50 | integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== 51 | dependencies: 52 | "@jridgewell/resolve-uri" "^3.1.0" 53 | "@jridgewell/sourcemap-codec" "^1.4.14" 54 | 55 | "@js-joda/core@3.2.0": 56 | version "3.2.0" 57 | resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-3.2.0.tgz#3e61e21b7b2b8a6be746df1335cf91d70db2a273" 58 | integrity sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg== 59 | 60 | "@socket.io/component-emitter@~3.1.0": 61 | version "3.1.0" 62 | resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" 63 | integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== 64 | 65 | "@types/cookie@^0.4.1": 66 | version "0.4.1" 67 | resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" 68 | integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== 69 | 70 | "@types/cors@^2.8.12": 71 | version "2.8.15" 72 | resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.15.tgz#eb143aa2f8807ddd78e83cbff141bbedd91b60ee" 73 | integrity sha512-n91JxbNLD8eQIuXDIChAN1tCKNWCEgpceU9b7ZMbFA+P+Q4yIeh80jizFLEvolRPc1ES0VdwFlGv+kJTSirogw== 74 | dependencies: 75 | "@types/node" "*" 76 | 77 | "@types/eslint-scope@^3.7.3": 78 | version "3.7.6" 79 | resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.6.tgz#585578b368ed170e67de8aae7b93f54a1b2fdc26" 80 | integrity sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ== 81 | dependencies: 82 | "@types/eslint" "*" 83 | "@types/estree" "*" 84 | 85 | "@types/eslint@*": 86 | version "8.44.6" 87 | resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.44.6.tgz#60e564551966dd255f4c01c459f0b4fb87068603" 88 | integrity sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw== 89 | dependencies: 90 | "@types/estree" "*" 91 | "@types/json-schema" "*" 92 | 93 | "@types/estree@*", "@types/estree@^1.0.0": 94 | version "1.0.4" 95 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.4.tgz#d9748f5742171b26218516cf1828b8eafaf8a9fa" 96 | integrity sha512-2JwWnHK9H+wUZNorf2Zr6ves96WHoWDJIftkcxPKsS7Djta6Zu519LarhRNljPXkpsZR2ZMwNCPeW7omW07BJw== 97 | 98 | "@types/json-schema@*", "@types/json-schema@^7.0.8": 99 | version "7.0.14" 100 | resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.14.tgz#74a97a5573980802f32c8e47b663530ab3b6b7d1" 101 | integrity sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw== 102 | 103 | "@types/node@*", "@types/node@>=10.0.0": 104 | version "20.8.10" 105 | resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.10.tgz#a5448b895c753ae929c26ce85cab557c6d4a365e" 106 | integrity sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w== 107 | dependencies: 108 | undici-types "~5.26.4" 109 | 110 | "@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": 111 | version "1.11.6" 112 | resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" 113 | integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== 114 | dependencies: 115 | "@webassemblyjs/helper-numbers" "1.11.6" 116 | "@webassemblyjs/helper-wasm-bytecode" "1.11.6" 117 | 118 | "@webassemblyjs/floating-point-hex-parser@1.11.6": 119 | version "1.11.6" 120 | resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" 121 | integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== 122 | 123 | "@webassemblyjs/helper-api-error@1.11.6": 124 | version "1.11.6" 125 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" 126 | integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== 127 | 128 | "@webassemblyjs/helper-buffer@1.11.6": 129 | version "1.11.6" 130 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" 131 | integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== 132 | 133 | "@webassemblyjs/helper-numbers@1.11.6": 134 | version "1.11.6" 135 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" 136 | integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== 137 | dependencies: 138 | "@webassemblyjs/floating-point-hex-parser" "1.11.6" 139 | "@webassemblyjs/helper-api-error" "1.11.6" 140 | "@xtuc/long" "4.2.2" 141 | 142 | "@webassemblyjs/helper-wasm-bytecode@1.11.6": 143 | version "1.11.6" 144 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" 145 | integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== 146 | 147 | "@webassemblyjs/helper-wasm-section@1.11.6": 148 | version "1.11.6" 149 | resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" 150 | integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== 151 | dependencies: 152 | "@webassemblyjs/ast" "1.11.6" 153 | "@webassemblyjs/helper-buffer" "1.11.6" 154 | "@webassemblyjs/helper-wasm-bytecode" "1.11.6" 155 | "@webassemblyjs/wasm-gen" "1.11.6" 156 | 157 | "@webassemblyjs/ieee754@1.11.6": 158 | version "1.11.6" 159 | resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" 160 | integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== 161 | dependencies: 162 | "@xtuc/ieee754" "^1.2.0" 163 | 164 | "@webassemblyjs/leb128@1.11.6": 165 | version "1.11.6" 166 | resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" 167 | integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== 168 | dependencies: 169 | "@xtuc/long" "4.2.2" 170 | 171 | "@webassemblyjs/utf8@1.11.6": 172 | version "1.11.6" 173 | resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" 174 | integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== 175 | 176 | "@webassemblyjs/wasm-edit@^1.11.5": 177 | version "1.11.6" 178 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" 179 | integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== 180 | dependencies: 181 | "@webassemblyjs/ast" "1.11.6" 182 | "@webassemblyjs/helper-buffer" "1.11.6" 183 | "@webassemblyjs/helper-wasm-bytecode" "1.11.6" 184 | "@webassemblyjs/helper-wasm-section" "1.11.6" 185 | "@webassemblyjs/wasm-gen" "1.11.6" 186 | "@webassemblyjs/wasm-opt" "1.11.6" 187 | "@webassemblyjs/wasm-parser" "1.11.6" 188 | "@webassemblyjs/wast-printer" "1.11.6" 189 | 190 | "@webassemblyjs/wasm-gen@1.11.6": 191 | version "1.11.6" 192 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" 193 | integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== 194 | dependencies: 195 | "@webassemblyjs/ast" "1.11.6" 196 | "@webassemblyjs/helper-wasm-bytecode" "1.11.6" 197 | "@webassemblyjs/ieee754" "1.11.6" 198 | "@webassemblyjs/leb128" "1.11.6" 199 | "@webassemblyjs/utf8" "1.11.6" 200 | 201 | "@webassemblyjs/wasm-opt@1.11.6": 202 | version "1.11.6" 203 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" 204 | integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== 205 | dependencies: 206 | "@webassemblyjs/ast" "1.11.6" 207 | "@webassemblyjs/helper-buffer" "1.11.6" 208 | "@webassemblyjs/wasm-gen" "1.11.6" 209 | "@webassemblyjs/wasm-parser" "1.11.6" 210 | 211 | "@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": 212 | version "1.11.6" 213 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" 214 | integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== 215 | dependencies: 216 | "@webassemblyjs/ast" "1.11.6" 217 | "@webassemblyjs/helper-api-error" "1.11.6" 218 | "@webassemblyjs/helper-wasm-bytecode" "1.11.6" 219 | "@webassemblyjs/ieee754" "1.11.6" 220 | "@webassemblyjs/leb128" "1.11.6" 221 | "@webassemblyjs/utf8" "1.11.6" 222 | 223 | "@webassemblyjs/wast-printer@1.11.6": 224 | version "1.11.6" 225 | resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" 226 | integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== 227 | dependencies: 228 | "@webassemblyjs/ast" "1.11.6" 229 | "@xtuc/long" "4.2.2" 230 | 231 | "@webpack-cli/configtest@^2.1.0": 232 | version "2.1.1" 233 | resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" 234 | integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== 235 | 236 | "@webpack-cli/info@^2.0.1": 237 | version "2.0.2" 238 | resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" 239 | integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== 240 | 241 | "@webpack-cli/serve@^2.0.3": 242 | version "2.0.5" 243 | resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" 244 | integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== 245 | 246 | "@xtuc/ieee754@^1.2.0": 247 | version "1.2.0" 248 | resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" 249 | integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== 250 | 251 | "@xtuc/long@4.2.2": 252 | version "4.2.2" 253 | resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" 254 | integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== 255 | 256 | abab@^2.0.6: 257 | version "2.0.6" 258 | resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" 259 | integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== 260 | 261 | accepts@~1.3.4: 262 | version "1.3.8" 263 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" 264 | integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 265 | dependencies: 266 | mime-types "~2.1.34" 267 | negotiator "0.6.3" 268 | 269 | acorn-import-assertions@^1.7.6: 270 | version "1.9.0" 271 | resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" 272 | integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== 273 | 274 | acorn@^8.7.1, acorn@^8.8.2: 275 | version "8.11.2" 276 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" 277 | integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== 278 | 279 | ajv-keywords@^3.5.2: 280 | version "3.5.2" 281 | resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" 282 | integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== 283 | 284 | ajv@^6.12.5: 285 | version "6.12.6" 286 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 287 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 288 | dependencies: 289 | fast-deep-equal "^3.1.1" 290 | fast-json-stable-stringify "^2.0.0" 291 | json-schema-traverse "^0.4.1" 292 | uri-js "^4.2.2" 293 | 294 | ansi-colors@4.1.1: 295 | version "4.1.1" 296 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 297 | integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 298 | 299 | ansi-regex@^5.0.1: 300 | version "5.0.1" 301 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 302 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 303 | 304 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 305 | version "4.3.0" 306 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 307 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 308 | dependencies: 309 | color-convert "^2.0.1" 310 | 311 | anymatch@~3.1.2: 312 | version "3.1.3" 313 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" 314 | integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== 315 | dependencies: 316 | normalize-path "^3.0.0" 317 | picomatch "^2.0.4" 318 | 319 | argparse@^2.0.1: 320 | version "2.0.1" 321 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 322 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 323 | 324 | balanced-match@^1.0.0: 325 | version "1.0.2" 326 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 327 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 328 | 329 | base64id@2.0.0, base64id@~2.0.0: 330 | version "2.0.0" 331 | resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" 332 | integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== 333 | 334 | binary-extensions@^2.0.0: 335 | version "2.2.0" 336 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" 337 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== 338 | 339 | body-parser@^1.19.0: 340 | version "1.20.2" 341 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" 342 | integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== 343 | dependencies: 344 | bytes "3.1.2" 345 | content-type "~1.0.5" 346 | debug "2.6.9" 347 | depd "2.0.0" 348 | destroy "1.2.0" 349 | http-errors "2.0.0" 350 | iconv-lite "0.4.24" 351 | on-finished "2.4.1" 352 | qs "6.11.0" 353 | raw-body "2.5.2" 354 | type-is "~1.6.18" 355 | unpipe "1.0.0" 356 | 357 | brace-expansion@^1.1.7: 358 | version "1.1.11" 359 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 360 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 361 | dependencies: 362 | balanced-match "^1.0.0" 363 | concat-map "0.0.1" 364 | 365 | brace-expansion@^2.0.1: 366 | version "2.0.1" 367 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 368 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 369 | dependencies: 370 | balanced-match "^1.0.0" 371 | 372 | braces@^3.0.2, braces@~3.0.2: 373 | version "3.0.2" 374 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 375 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 376 | dependencies: 377 | fill-range "^7.0.1" 378 | 379 | browser-stdout@1.3.1: 380 | version "1.3.1" 381 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 382 | integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== 383 | 384 | browserslist@^4.14.5: 385 | version "4.22.1" 386 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.1.tgz#ba91958d1a59b87dab6fed8dfbcb3da5e2e9c619" 387 | integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ== 388 | dependencies: 389 | caniuse-lite "^1.0.30001541" 390 | electron-to-chromium "^1.4.535" 391 | node-releases "^2.0.13" 392 | update-browserslist-db "^1.0.13" 393 | 394 | buffer-from@^1.0.0: 395 | version "1.1.2" 396 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" 397 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 398 | 399 | bytes@3.1.2: 400 | version "3.1.2" 401 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 402 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 403 | 404 | call-bind@^1.0.0: 405 | version "1.0.5" 406 | resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" 407 | integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== 408 | dependencies: 409 | function-bind "^1.1.2" 410 | get-intrinsic "^1.2.1" 411 | set-function-length "^1.1.1" 412 | 413 | camelcase@^6.0.0: 414 | version "6.3.0" 415 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" 416 | integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== 417 | 418 | caniuse-lite@^1.0.30001541: 419 | version "1.0.30001559" 420 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz#95a982440d3d314c471db68d02664fb7536c5a30" 421 | integrity sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA== 422 | 423 | chalk@^4.1.0: 424 | version "4.1.2" 425 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 426 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 427 | dependencies: 428 | ansi-styles "^4.1.0" 429 | supports-color "^7.1.0" 430 | 431 | chokidar@3.5.3, chokidar@^3.5.1: 432 | version "3.5.3" 433 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" 434 | integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== 435 | dependencies: 436 | anymatch "~3.1.2" 437 | braces "~3.0.2" 438 | glob-parent "~5.1.2" 439 | is-binary-path "~2.1.0" 440 | is-glob "~4.0.1" 441 | normalize-path "~3.0.0" 442 | readdirp "~3.6.0" 443 | optionalDependencies: 444 | fsevents "~2.3.2" 445 | 446 | chrome-trace-event@^1.0.2: 447 | version "1.0.3" 448 | resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" 449 | integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== 450 | 451 | cliui@^7.0.2: 452 | version "7.0.4" 453 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 454 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== 455 | dependencies: 456 | string-width "^4.2.0" 457 | strip-ansi "^6.0.0" 458 | wrap-ansi "^7.0.0" 459 | 460 | clone-deep@^4.0.1: 461 | version "4.0.1" 462 | resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" 463 | integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== 464 | dependencies: 465 | is-plain-object "^2.0.4" 466 | kind-of "^6.0.2" 467 | shallow-clone "^3.0.0" 468 | 469 | color-convert@^2.0.1: 470 | version "2.0.1" 471 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 472 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 473 | dependencies: 474 | color-name "~1.1.4" 475 | 476 | color-name@~1.1.4: 477 | version "1.1.4" 478 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 479 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 480 | 481 | colorette@^2.0.14: 482 | version "2.0.20" 483 | resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" 484 | integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== 485 | 486 | commander@^10.0.1: 487 | version "10.0.1" 488 | resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" 489 | integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== 490 | 491 | commander@^2.20.0: 492 | version "2.20.3" 493 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 494 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 495 | 496 | concat-map@0.0.1: 497 | version "0.0.1" 498 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 499 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 500 | 501 | connect@^3.7.0: 502 | version "3.7.0" 503 | resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" 504 | integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== 505 | dependencies: 506 | debug "2.6.9" 507 | finalhandler "1.1.2" 508 | parseurl "~1.3.3" 509 | utils-merge "1.0.1" 510 | 511 | content-type@~1.0.5: 512 | version "1.0.5" 513 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" 514 | integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== 515 | 516 | cookie@~0.4.1: 517 | version "0.4.2" 518 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" 519 | integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== 520 | 521 | cors@~2.8.5: 522 | version "2.8.5" 523 | resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" 524 | integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== 525 | dependencies: 526 | object-assign "^4" 527 | vary "^1" 528 | 529 | cross-spawn@^7.0.3: 530 | version "7.0.3" 531 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 532 | integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 533 | dependencies: 534 | path-key "^3.1.0" 535 | shebang-command "^2.0.0" 536 | which "^2.0.1" 537 | 538 | custom-event@~1.0.0: 539 | version "1.0.1" 540 | resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" 541 | integrity sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg== 542 | 543 | date-format@^4.0.14: 544 | version "4.0.14" 545 | resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" 546 | integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== 547 | 548 | debug@2.6.9: 549 | version "2.6.9" 550 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 551 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 552 | dependencies: 553 | ms "2.0.0" 554 | 555 | debug@4.3.4, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: 556 | version "4.3.4" 557 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 558 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 559 | dependencies: 560 | ms "2.1.2" 561 | 562 | decamelize@^4.0.0: 563 | version "4.0.0" 564 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" 565 | integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== 566 | 567 | define-data-property@^1.1.1: 568 | version "1.1.1" 569 | resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" 570 | integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== 571 | dependencies: 572 | get-intrinsic "^1.2.1" 573 | gopd "^1.0.1" 574 | has-property-descriptors "^1.0.0" 575 | 576 | depd@2.0.0: 577 | version "2.0.0" 578 | resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 579 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 580 | 581 | destroy@1.2.0: 582 | version "1.2.0" 583 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" 584 | integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 585 | 586 | di@^0.0.1: 587 | version "0.0.1" 588 | resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" 589 | integrity sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA== 590 | 591 | diff@5.0.0: 592 | version "5.0.0" 593 | resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" 594 | integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== 595 | 596 | dom-serialize@^2.2.1: 597 | version "2.2.1" 598 | resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" 599 | integrity sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ== 600 | dependencies: 601 | custom-event "~1.0.0" 602 | ent "~2.2.0" 603 | extend "^3.0.0" 604 | void-elements "^2.0.0" 605 | 606 | ee-first@1.1.1: 607 | version "1.1.1" 608 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 609 | integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== 610 | 611 | electron-to-chromium@^1.4.535: 612 | version "1.4.575" 613 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.575.tgz#7c0b87eb2c6214a993699792abd704de41255c39" 614 | integrity sha512-kY2BGyvgAHiX899oF6xLXSIf99bAvvdPhDoJwG77nxCSyWYuRH6e9a9a3gpXBvCs6lj4dQZJkfnW2hdKWHEISg== 615 | 616 | emoji-regex@^8.0.0: 617 | version "8.0.0" 618 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 619 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 620 | 621 | encodeurl@~1.0.2: 622 | version "1.0.2" 623 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 624 | integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== 625 | 626 | engine.io-parser@~5.2.1: 627 | version "5.2.1" 628 | resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.1.tgz#9f213c77512ff1a6cc0c7a86108a7ffceb16fcfb" 629 | integrity sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ== 630 | 631 | engine.io@~6.5.2: 632 | version "6.5.3" 633 | resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.5.3.tgz#80b0692912cef3a417e1b7433301d6397bf0374b" 634 | integrity sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw== 635 | dependencies: 636 | "@types/cookie" "^0.4.1" 637 | "@types/cors" "^2.8.12" 638 | "@types/node" ">=10.0.0" 639 | accepts "~1.3.4" 640 | base64id "2.0.0" 641 | cookie "~0.4.1" 642 | cors "~2.8.5" 643 | debug "~4.3.1" 644 | engine.io-parser "~5.2.1" 645 | ws "~8.11.0" 646 | 647 | enhanced-resolve@^5.13.0: 648 | version "5.15.0" 649 | resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" 650 | integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== 651 | dependencies: 652 | graceful-fs "^4.2.4" 653 | tapable "^2.2.0" 654 | 655 | ent@~2.2.0: 656 | version "2.2.0" 657 | resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" 658 | integrity sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA== 659 | 660 | envinfo@^7.7.3: 661 | version "7.11.0" 662 | resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.11.0.tgz#c3793f44284a55ff8c82faf1ffd91bc6478ea01f" 663 | integrity sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg== 664 | 665 | es-module-lexer@^1.2.1: 666 | version "1.3.1" 667 | resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.1.tgz#c1b0dd5ada807a3b3155315911f364dc4e909db1" 668 | integrity sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q== 669 | 670 | escalade@^3.1.1: 671 | version "3.1.1" 672 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 673 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 674 | 675 | escape-html@~1.0.3: 676 | version "1.0.3" 677 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 678 | integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 679 | 680 | escape-string-regexp@4.0.0: 681 | version "4.0.0" 682 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 683 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 684 | 685 | eslint-scope@5.1.1: 686 | version "5.1.1" 687 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" 688 | integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== 689 | dependencies: 690 | esrecurse "^4.3.0" 691 | estraverse "^4.1.1" 692 | 693 | esrecurse@^4.3.0: 694 | version "4.3.0" 695 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 696 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 697 | dependencies: 698 | estraverse "^5.2.0" 699 | 700 | estraverse@^4.1.1: 701 | version "4.3.0" 702 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" 703 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 704 | 705 | estraverse@^5.2.0: 706 | version "5.3.0" 707 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" 708 | integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 709 | 710 | eventemitter3@^4.0.0: 711 | version "4.0.7" 712 | resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" 713 | integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== 714 | 715 | events@^3.2.0: 716 | version "3.3.0" 717 | resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" 718 | integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== 719 | 720 | extend@^3.0.0: 721 | version "3.0.2" 722 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 723 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== 724 | 725 | fast-deep-equal@^3.1.1: 726 | version "3.1.3" 727 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 728 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 729 | 730 | fast-json-stable-stringify@^2.0.0: 731 | version "2.1.0" 732 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 733 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 734 | 735 | fastest-levenshtein@^1.0.12: 736 | version "1.0.16" 737 | resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" 738 | integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== 739 | 740 | fill-range@^7.0.1: 741 | version "7.0.1" 742 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 743 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 744 | dependencies: 745 | to-regex-range "^5.0.1" 746 | 747 | finalhandler@1.1.2: 748 | version "1.1.2" 749 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" 750 | integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== 751 | dependencies: 752 | debug "2.6.9" 753 | encodeurl "~1.0.2" 754 | escape-html "~1.0.3" 755 | on-finished "~2.3.0" 756 | parseurl "~1.3.3" 757 | statuses "~1.5.0" 758 | unpipe "~1.0.0" 759 | 760 | find-up@5.0.0: 761 | version "5.0.0" 762 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 763 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 764 | dependencies: 765 | locate-path "^6.0.0" 766 | path-exists "^4.0.0" 767 | 768 | find-up@^4.0.0: 769 | version "4.1.0" 770 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 771 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 772 | dependencies: 773 | locate-path "^5.0.0" 774 | path-exists "^4.0.0" 775 | 776 | flat@^5.0.2: 777 | version "5.0.2" 778 | resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" 779 | integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== 780 | 781 | flatted@^3.2.7: 782 | version "3.2.9" 783 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" 784 | integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== 785 | 786 | follow-redirects@^1.0.0: 787 | version "1.15.3" 788 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" 789 | integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== 790 | 791 | format-util@^1.0.5: 792 | version "1.0.5" 793 | resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.5.tgz#1ffb450c8a03e7bccffe40643180918cc297d271" 794 | integrity sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg== 795 | 796 | fs-extra@^8.1.0: 797 | version "8.1.0" 798 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" 799 | integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== 800 | dependencies: 801 | graceful-fs "^4.2.0" 802 | jsonfile "^4.0.0" 803 | universalify "^0.1.0" 804 | 805 | fs.realpath@^1.0.0: 806 | version "1.0.0" 807 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 808 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== 809 | 810 | fsevents@~2.3.2: 811 | version "2.3.3" 812 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" 813 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 814 | 815 | function-bind@^1.1.2: 816 | version "1.1.2" 817 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" 818 | integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 819 | 820 | get-caller-file@^2.0.5: 821 | version "2.0.5" 822 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 823 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 824 | 825 | get-intrinsic@^1.0.2, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: 826 | version "1.2.2" 827 | resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" 828 | integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== 829 | dependencies: 830 | function-bind "^1.1.2" 831 | has-proto "^1.0.1" 832 | has-symbols "^1.0.3" 833 | hasown "^2.0.0" 834 | 835 | glob-parent@~5.1.2: 836 | version "5.1.2" 837 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 838 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 839 | dependencies: 840 | is-glob "^4.0.1" 841 | 842 | glob-to-regexp@^0.4.1: 843 | version "0.4.1" 844 | resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" 845 | integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== 846 | 847 | glob@7.2.0: 848 | version "7.2.0" 849 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" 850 | integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== 851 | dependencies: 852 | fs.realpath "^1.0.0" 853 | inflight "^1.0.4" 854 | inherits "2" 855 | minimatch "^3.0.4" 856 | once "^1.3.0" 857 | path-is-absolute "^1.0.0" 858 | 859 | glob@^7.1.3, glob@^7.1.7: 860 | version "7.2.3" 861 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" 862 | integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== 863 | dependencies: 864 | fs.realpath "^1.0.0" 865 | inflight "^1.0.4" 866 | inherits "2" 867 | minimatch "^3.1.1" 868 | once "^1.3.0" 869 | path-is-absolute "^1.0.0" 870 | 871 | gopd@^1.0.1: 872 | version "1.0.1" 873 | resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" 874 | integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== 875 | dependencies: 876 | get-intrinsic "^1.1.3" 877 | 878 | graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: 879 | version "4.2.11" 880 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" 881 | integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== 882 | 883 | has-flag@^4.0.0: 884 | version "4.0.0" 885 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 886 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 887 | 888 | has-property-descriptors@^1.0.0: 889 | version "1.0.1" 890 | resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" 891 | integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== 892 | dependencies: 893 | get-intrinsic "^1.2.2" 894 | 895 | has-proto@^1.0.1: 896 | version "1.0.1" 897 | resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" 898 | integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== 899 | 900 | has-symbols@^1.0.3: 901 | version "1.0.3" 902 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 903 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 904 | 905 | hasown@^2.0.0: 906 | version "2.0.0" 907 | resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" 908 | integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== 909 | dependencies: 910 | function-bind "^1.1.2" 911 | 912 | he@1.2.0: 913 | version "1.2.0" 914 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 915 | integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 916 | 917 | http-errors@2.0.0: 918 | version "2.0.0" 919 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 920 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 921 | dependencies: 922 | depd "2.0.0" 923 | inherits "2.0.4" 924 | setprototypeof "1.2.0" 925 | statuses "2.0.1" 926 | toidentifier "1.0.1" 927 | 928 | http-proxy@^1.18.1: 929 | version "1.18.1" 930 | resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" 931 | integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== 932 | dependencies: 933 | eventemitter3 "^4.0.0" 934 | follow-redirects "^1.0.0" 935 | requires-port "^1.0.0" 936 | 937 | iconv-lite@0.4.24: 938 | version "0.4.24" 939 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 940 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 941 | dependencies: 942 | safer-buffer ">= 2.1.2 < 3" 943 | 944 | iconv-lite@^0.6.3: 945 | version "0.6.3" 946 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" 947 | integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== 948 | dependencies: 949 | safer-buffer ">= 2.1.2 < 3.0.0" 950 | 951 | import-local@^3.0.2: 952 | version "3.1.0" 953 | resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" 954 | integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== 955 | dependencies: 956 | pkg-dir "^4.2.0" 957 | resolve-cwd "^3.0.0" 958 | 959 | inflight@^1.0.4: 960 | version "1.0.6" 961 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 962 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== 963 | dependencies: 964 | once "^1.3.0" 965 | wrappy "1" 966 | 967 | inherits@2, inherits@2.0.4: 968 | version "2.0.4" 969 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 970 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 971 | 972 | interpret@^3.1.1: 973 | version "3.1.1" 974 | resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" 975 | integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== 976 | 977 | is-binary-path@~2.1.0: 978 | version "2.1.0" 979 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 980 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 981 | dependencies: 982 | binary-extensions "^2.0.0" 983 | 984 | is-core-module@^2.13.0: 985 | version "2.13.1" 986 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" 987 | integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== 988 | dependencies: 989 | hasown "^2.0.0" 990 | 991 | is-extglob@^2.1.1: 992 | version "2.1.1" 993 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 994 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 995 | 996 | is-fullwidth-code-point@^3.0.0: 997 | version "3.0.0" 998 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 999 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 1000 | 1001 | is-glob@^4.0.1, is-glob@~4.0.1: 1002 | version "4.0.3" 1003 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 1004 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 1005 | dependencies: 1006 | is-extglob "^2.1.1" 1007 | 1008 | is-number@^7.0.0: 1009 | version "7.0.0" 1010 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 1011 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 1012 | 1013 | is-plain-obj@^2.1.0: 1014 | version "2.1.0" 1015 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" 1016 | integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== 1017 | 1018 | is-plain-object@^2.0.4: 1019 | version "2.0.4" 1020 | resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" 1021 | integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== 1022 | dependencies: 1023 | isobject "^3.0.1" 1024 | 1025 | is-unicode-supported@^0.1.0: 1026 | version "0.1.0" 1027 | resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" 1028 | integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== 1029 | 1030 | isbinaryfile@^4.0.8: 1031 | version "4.0.10" 1032 | resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" 1033 | integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== 1034 | 1035 | isexe@^2.0.0: 1036 | version "2.0.0" 1037 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 1038 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 1039 | 1040 | isobject@^3.0.1: 1041 | version "3.0.1" 1042 | resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" 1043 | integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== 1044 | 1045 | jest-worker@^27.4.5: 1046 | version "27.5.1" 1047 | resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" 1048 | integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== 1049 | dependencies: 1050 | "@types/node" "*" 1051 | merge-stream "^2.0.0" 1052 | supports-color "^8.0.0" 1053 | 1054 | js-yaml@4.1.0: 1055 | version "4.1.0" 1056 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 1057 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 1058 | dependencies: 1059 | argparse "^2.0.1" 1060 | 1061 | json-parse-even-better-errors@^2.3.1: 1062 | version "2.3.1" 1063 | resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" 1064 | integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== 1065 | 1066 | json-schema-traverse@^0.4.1: 1067 | version "0.4.1" 1068 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 1069 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 1070 | 1071 | jsonfile@^4.0.0: 1072 | version "4.0.0" 1073 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" 1074 | integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== 1075 | optionalDependencies: 1076 | graceful-fs "^4.1.6" 1077 | 1078 | karma-chrome-launcher@3.2.0: 1079 | version "3.2.0" 1080 | resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz#eb9c95024f2d6dfbb3748d3415ac9b381906b9a9" 1081 | integrity sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q== 1082 | dependencies: 1083 | which "^1.2.1" 1084 | 1085 | karma-mocha@2.0.1: 1086 | version "2.0.1" 1087 | resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-2.0.1.tgz#4b0254a18dfee71bdbe6188d9a6861bf86b0cd7d" 1088 | integrity sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ== 1089 | dependencies: 1090 | minimist "^1.2.3" 1091 | 1092 | karma-sourcemap-loader@0.4.0: 1093 | version "0.4.0" 1094 | resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.4.0.tgz#b01d73f8f688f533bcc8f5d273d43458e13b5488" 1095 | integrity sha512-xCRL3/pmhAYF3I6qOrcn0uhbQevitc2DERMPH82FMnG+4WReoGcGFZb1pURf2a5apyrOHRdvD+O6K7NljqKHyA== 1096 | dependencies: 1097 | graceful-fs "^4.2.10" 1098 | 1099 | karma-webpack@5.0.0: 1100 | version "5.0.0" 1101 | resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-5.0.0.tgz#2a2c7b80163fe7ffd1010f83f5507f95ef39f840" 1102 | integrity sha512-+54i/cd3/piZuP3dr54+NcFeKOPnys5QeM1IY+0SPASwrtHsliXUiCL50iW+K9WWA7RvamC4macvvQ86l3KtaA== 1103 | dependencies: 1104 | glob "^7.1.3" 1105 | minimatch "^3.0.4" 1106 | webpack-merge "^4.1.5" 1107 | 1108 | karma@6.4.2: 1109 | version "6.4.2" 1110 | resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.2.tgz#a983f874cee6f35990c4b2dcc3d274653714de8e" 1111 | integrity sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ== 1112 | dependencies: 1113 | "@colors/colors" "1.5.0" 1114 | body-parser "^1.19.0" 1115 | braces "^3.0.2" 1116 | chokidar "^3.5.1" 1117 | connect "^3.7.0" 1118 | di "^0.0.1" 1119 | dom-serialize "^2.2.1" 1120 | glob "^7.1.7" 1121 | graceful-fs "^4.2.6" 1122 | http-proxy "^1.18.1" 1123 | isbinaryfile "^4.0.8" 1124 | lodash "^4.17.21" 1125 | log4js "^6.4.1" 1126 | mime "^2.5.2" 1127 | minimatch "^3.0.4" 1128 | mkdirp "^0.5.5" 1129 | qjobs "^1.2.0" 1130 | range-parser "^1.2.1" 1131 | rimraf "^3.0.2" 1132 | socket.io "^4.4.1" 1133 | source-map "^0.6.1" 1134 | tmp "^0.2.1" 1135 | ua-parser-js "^0.7.30" 1136 | yargs "^16.1.1" 1137 | 1138 | kind-of@^6.0.2: 1139 | version "6.0.3" 1140 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" 1141 | integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== 1142 | 1143 | loader-runner@^4.2.0: 1144 | version "4.3.0" 1145 | resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" 1146 | integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== 1147 | 1148 | locate-path@^5.0.0: 1149 | version "5.0.0" 1150 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 1151 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 1152 | dependencies: 1153 | p-locate "^4.1.0" 1154 | 1155 | locate-path@^6.0.0: 1156 | version "6.0.0" 1157 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 1158 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 1159 | dependencies: 1160 | p-locate "^5.0.0" 1161 | 1162 | lodash@^4.17.15, lodash@^4.17.21: 1163 | version "4.17.21" 1164 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 1165 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 1166 | 1167 | log-symbols@4.1.0: 1168 | version "4.1.0" 1169 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" 1170 | integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== 1171 | dependencies: 1172 | chalk "^4.1.0" 1173 | is-unicode-supported "^0.1.0" 1174 | 1175 | log4js@^6.4.1: 1176 | version "6.9.1" 1177 | resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.9.1.tgz#aba5a3ff4e7872ae34f8b4c533706753709e38b6" 1178 | integrity sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g== 1179 | dependencies: 1180 | date-format "^4.0.14" 1181 | debug "^4.3.4" 1182 | flatted "^3.2.7" 1183 | rfdc "^1.3.0" 1184 | streamroller "^3.1.5" 1185 | 1186 | media-typer@0.3.0: 1187 | version "0.3.0" 1188 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 1189 | integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== 1190 | 1191 | merge-stream@^2.0.0: 1192 | version "2.0.0" 1193 | resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" 1194 | integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== 1195 | 1196 | mime-db@1.52.0: 1197 | version "1.52.0" 1198 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 1199 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 1200 | 1201 | mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34: 1202 | version "2.1.35" 1203 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 1204 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 1205 | dependencies: 1206 | mime-db "1.52.0" 1207 | 1208 | mime@^2.5.2: 1209 | version "2.6.0" 1210 | resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" 1211 | integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== 1212 | 1213 | minimatch@5.0.1: 1214 | version "5.0.1" 1215 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" 1216 | integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== 1217 | dependencies: 1218 | brace-expansion "^2.0.1" 1219 | 1220 | minimatch@^3.0.4, minimatch@^3.1.1: 1221 | version "3.1.2" 1222 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 1223 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 1224 | dependencies: 1225 | brace-expansion "^1.1.7" 1226 | 1227 | minimist@^1.2.3, minimist@^1.2.6: 1228 | version "1.2.8" 1229 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" 1230 | integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== 1231 | 1232 | mkdirp@^0.5.5: 1233 | version "0.5.6" 1234 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" 1235 | integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== 1236 | dependencies: 1237 | minimist "^1.2.6" 1238 | 1239 | mocha@10.2.0: 1240 | version "10.2.0" 1241 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" 1242 | integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== 1243 | dependencies: 1244 | ansi-colors "4.1.1" 1245 | browser-stdout "1.3.1" 1246 | chokidar "3.5.3" 1247 | debug "4.3.4" 1248 | diff "5.0.0" 1249 | escape-string-regexp "4.0.0" 1250 | find-up "5.0.0" 1251 | glob "7.2.0" 1252 | he "1.2.0" 1253 | js-yaml "4.1.0" 1254 | log-symbols "4.1.0" 1255 | minimatch "5.0.1" 1256 | ms "2.1.3" 1257 | nanoid "3.3.3" 1258 | serialize-javascript "6.0.0" 1259 | strip-json-comments "3.1.1" 1260 | supports-color "8.1.1" 1261 | workerpool "6.2.1" 1262 | yargs "16.2.0" 1263 | yargs-parser "20.2.4" 1264 | yargs-unparser "2.0.0" 1265 | 1266 | ms@2.0.0: 1267 | version "2.0.0" 1268 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 1269 | integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 1270 | 1271 | ms@2.1.2: 1272 | version "2.1.2" 1273 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 1274 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 1275 | 1276 | ms@2.1.3: 1277 | version "2.1.3" 1278 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 1279 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 1280 | 1281 | nanoid@3.3.3: 1282 | version "3.3.3" 1283 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" 1284 | integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== 1285 | 1286 | negotiator@0.6.3: 1287 | version "0.6.3" 1288 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" 1289 | integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 1290 | 1291 | neo-async@^2.6.2: 1292 | version "2.6.2" 1293 | resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" 1294 | integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== 1295 | 1296 | node-releases@^2.0.13: 1297 | version "2.0.13" 1298 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" 1299 | integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== 1300 | 1301 | normalize-path@^3.0.0, normalize-path@~3.0.0: 1302 | version "3.0.0" 1303 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 1304 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 1305 | 1306 | object-assign@^4: 1307 | version "4.1.1" 1308 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 1309 | integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== 1310 | 1311 | object-inspect@^1.9.0: 1312 | version "1.13.1" 1313 | resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" 1314 | integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== 1315 | 1316 | on-finished@2.4.1: 1317 | version "2.4.1" 1318 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" 1319 | integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 1320 | dependencies: 1321 | ee-first "1.1.1" 1322 | 1323 | on-finished@~2.3.0: 1324 | version "2.3.0" 1325 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 1326 | integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== 1327 | dependencies: 1328 | ee-first "1.1.1" 1329 | 1330 | once@^1.3.0: 1331 | version "1.4.0" 1332 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1333 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== 1334 | dependencies: 1335 | wrappy "1" 1336 | 1337 | p-limit@^2.2.0: 1338 | version "2.3.0" 1339 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 1340 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 1341 | dependencies: 1342 | p-try "^2.0.0" 1343 | 1344 | p-limit@^3.0.2: 1345 | version "3.1.0" 1346 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 1347 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 1348 | dependencies: 1349 | yocto-queue "^0.1.0" 1350 | 1351 | p-locate@^4.1.0: 1352 | version "4.1.0" 1353 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 1354 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 1355 | dependencies: 1356 | p-limit "^2.2.0" 1357 | 1358 | p-locate@^5.0.0: 1359 | version "5.0.0" 1360 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 1361 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 1362 | dependencies: 1363 | p-limit "^3.0.2" 1364 | 1365 | p-try@^2.0.0: 1366 | version "2.2.0" 1367 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 1368 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 1369 | 1370 | parseurl@~1.3.3: 1371 | version "1.3.3" 1372 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 1373 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 1374 | 1375 | path-exists@^4.0.0: 1376 | version "4.0.0" 1377 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 1378 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1379 | 1380 | path-is-absolute@^1.0.0: 1381 | version "1.0.1" 1382 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1383 | integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== 1384 | 1385 | path-key@^3.1.0: 1386 | version "3.1.1" 1387 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 1388 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 1389 | 1390 | path-parse@^1.0.7: 1391 | version "1.0.7" 1392 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 1393 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 1394 | 1395 | picocolors@^1.0.0: 1396 | version "1.0.0" 1397 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" 1398 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== 1399 | 1400 | picomatch@^2.0.4, picomatch@^2.2.1: 1401 | version "2.3.1" 1402 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 1403 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 1404 | 1405 | pkg-dir@^4.2.0: 1406 | version "4.2.0" 1407 | resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" 1408 | integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== 1409 | dependencies: 1410 | find-up "^4.0.0" 1411 | 1412 | punycode@^2.1.0: 1413 | version "2.3.1" 1414 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" 1415 | integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== 1416 | 1417 | qjobs@^1.2.0: 1418 | version "1.2.0" 1419 | resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" 1420 | integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== 1421 | 1422 | qs@6.11.0: 1423 | version "6.11.0" 1424 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" 1425 | integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== 1426 | dependencies: 1427 | side-channel "^1.0.4" 1428 | 1429 | randombytes@^2.1.0: 1430 | version "2.1.0" 1431 | resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 1432 | integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== 1433 | dependencies: 1434 | safe-buffer "^5.1.0" 1435 | 1436 | range-parser@^1.2.1: 1437 | version "1.2.1" 1438 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 1439 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 1440 | 1441 | raw-body@2.5.2: 1442 | version "2.5.2" 1443 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" 1444 | integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== 1445 | dependencies: 1446 | bytes "3.1.2" 1447 | http-errors "2.0.0" 1448 | iconv-lite "0.4.24" 1449 | unpipe "1.0.0" 1450 | 1451 | readdirp@~3.6.0: 1452 | version "3.6.0" 1453 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" 1454 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== 1455 | dependencies: 1456 | picomatch "^2.2.1" 1457 | 1458 | rechoir@^0.8.0: 1459 | version "0.8.0" 1460 | resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" 1461 | integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== 1462 | dependencies: 1463 | resolve "^1.20.0" 1464 | 1465 | require-directory@^2.1.1: 1466 | version "2.1.1" 1467 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 1468 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 1469 | 1470 | requires-port@^1.0.0: 1471 | version "1.0.0" 1472 | resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 1473 | integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== 1474 | 1475 | resolve-cwd@^3.0.0: 1476 | version "3.0.0" 1477 | resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" 1478 | integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== 1479 | dependencies: 1480 | resolve-from "^5.0.0" 1481 | 1482 | resolve-from@^5.0.0: 1483 | version "5.0.0" 1484 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" 1485 | integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== 1486 | 1487 | resolve@^1.20.0: 1488 | version "1.22.8" 1489 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" 1490 | integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== 1491 | dependencies: 1492 | is-core-module "^2.13.0" 1493 | path-parse "^1.0.7" 1494 | supports-preserve-symlinks-flag "^1.0.0" 1495 | 1496 | rfdc@^1.3.0: 1497 | version "1.3.0" 1498 | resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" 1499 | integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== 1500 | 1501 | rimraf@^3.0.0, rimraf@^3.0.2: 1502 | version "3.0.2" 1503 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 1504 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1505 | dependencies: 1506 | glob "^7.1.3" 1507 | 1508 | safe-buffer@^5.1.0: 1509 | version "5.2.1" 1510 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1511 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 1512 | 1513 | "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": 1514 | version "2.1.2" 1515 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1516 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 1517 | 1518 | schema-utils@^3.1.1, schema-utils@^3.1.2: 1519 | version "3.3.0" 1520 | resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" 1521 | integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== 1522 | dependencies: 1523 | "@types/json-schema" "^7.0.8" 1524 | ajv "^6.12.5" 1525 | ajv-keywords "^3.5.2" 1526 | 1527 | serialize-javascript@6.0.0: 1528 | version "6.0.0" 1529 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" 1530 | integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== 1531 | dependencies: 1532 | randombytes "^2.1.0" 1533 | 1534 | serialize-javascript@^6.0.1: 1535 | version "6.0.1" 1536 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" 1537 | integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== 1538 | dependencies: 1539 | randombytes "^2.1.0" 1540 | 1541 | set-function-length@^1.1.1: 1542 | version "1.1.1" 1543 | resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" 1544 | integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== 1545 | dependencies: 1546 | define-data-property "^1.1.1" 1547 | get-intrinsic "^1.2.1" 1548 | gopd "^1.0.1" 1549 | has-property-descriptors "^1.0.0" 1550 | 1551 | setprototypeof@1.2.0: 1552 | version "1.2.0" 1553 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 1554 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 1555 | 1556 | shallow-clone@^3.0.0: 1557 | version "3.0.1" 1558 | resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" 1559 | integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== 1560 | dependencies: 1561 | kind-of "^6.0.2" 1562 | 1563 | shebang-command@^2.0.0: 1564 | version "2.0.0" 1565 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 1566 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1567 | dependencies: 1568 | shebang-regex "^3.0.0" 1569 | 1570 | shebang-regex@^3.0.0: 1571 | version "3.0.0" 1572 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 1573 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1574 | 1575 | side-channel@^1.0.4: 1576 | version "1.0.4" 1577 | resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" 1578 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 1579 | dependencies: 1580 | call-bind "^1.0.0" 1581 | get-intrinsic "^1.0.2" 1582 | object-inspect "^1.9.0" 1583 | 1584 | socket.io-adapter@~2.5.2: 1585 | version "2.5.2" 1586 | resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12" 1587 | integrity sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA== 1588 | dependencies: 1589 | ws "~8.11.0" 1590 | 1591 | socket.io-parser@~4.2.4: 1592 | version "4.2.4" 1593 | resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" 1594 | integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== 1595 | dependencies: 1596 | "@socket.io/component-emitter" "~3.1.0" 1597 | debug "~4.3.1" 1598 | 1599 | socket.io@^4.4.1: 1600 | version "4.7.2" 1601 | resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.2.tgz#22557d76c3f3ca48f82e73d68b7add36a22df002" 1602 | integrity sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw== 1603 | dependencies: 1604 | accepts "~1.3.4" 1605 | base64id "~2.0.0" 1606 | cors "~2.8.5" 1607 | debug "~4.3.2" 1608 | engine.io "~6.5.2" 1609 | socket.io-adapter "~2.5.2" 1610 | socket.io-parser "~4.2.4" 1611 | 1612 | source-map-js@^1.0.2: 1613 | version "1.0.2" 1614 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" 1615 | integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== 1616 | 1617 | source-map-loader@4.0.1: 1618 | version "4.0.1" 1619 | resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-4.0.1.tgz#72f00d05f5d1f90f80974eda781cbd7107c125f2" 1620 | integrity sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA== 1621 | dependencies: 1622 | abab "^2.0.6" 1623 | iconv-lite "^0.6.3" 1624 | source-map-js "^1.0.2" 1625 | 1626 | source-map-support@0.5.21, source-map-support@~0.5.20: 1627 | version "0.5.21" 1628 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" 1629 | integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== 1630 | dependencies: 1631 | buffer-from "^1.0.0" 1632 | source-map "^0.6.0" 1633 | 1634 | source-map@^0.6.0, source-map@^0.6.1: 1635 | version "0.6.1" 1636 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1637 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1638 | 1639 | statuses@2.0.1: 1640 | version "2.0.1" 1641 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 1642 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 1643 | 1644 | statuses@~1.5.0: 1645 | version "1.5.0" 1646 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" 1647 | integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== 1648 | 1649 | streamroller@^3.1.5: 1650 | version "3.1.5" 1651 | resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.5.tgz#1263182329a45def1ffaef58d31b15d13d2ee7ff" 1652 | integrity sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw== 1653 | dependencies: 1654 | date-format "^4.0.14" 1655 | debug "^4.3.4" 1656 | fs-extra "^8.1.0" 1657 | 1658 | string-width@^4.1.0, string-width@^4.2.0: 1659 | version "4.2.3" 1660 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 1661 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 1662 | dependencies: 1663 | emoji-regex "^8.0.0" 1664 | is-fullwidth-code-point "^3.0.0" 1665 | strip-ansi "^6.0.1" 1666 | 1667 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 1668 | version "6.0.1" 1669 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1670 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1671 | dependencies: 1672 | ansi-regex "^5.0.1" 1673 | 1674 | strip-json-comments@3.1.1: 1675 | version "3.1.1" 1676 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1677 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1678 | 1679 | supports-color@8.1.1, supports-color@^8.0.0: 1680 | version "8.1.1" 1681 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 1682 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 1683 | dependencies: 1684 | has-flag "^4.0.0" 1685 | 1686 | supports-color@^7.1.0: 1687 | version "7.2.0" 1688 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1689 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1690 | dependencies: 1691 | has-flag "^4.0.0" 1692 | 1693 | supports-preserve-symlinks-flag@^1.0.0: 1694 | version "1.0.0" 1695 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" 1696 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 1697 | 1698 | tapable@^2.1.1, tapable@^2.2.0: 1699 | version "2.2.1" 1700 | resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" 1701 | integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== 1702 | 1703 | terser-webpack-plugin@^5.3.7: 1704 | version "5.3.9" 1705 | resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" 1706 | integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== 1707 | dependencies: 1708 | "@jridgewell/trace-mapping" "^0.3.17" 1709 | jest-worker "^27.4.5" 1710 | schema-utils "^3.1.1" 1711 | serialize-javascript "^6.0.1" 1712 | terser "^5.16.8" 1713 | 1714 | terser@^5.16.8: 1715 | version "5.24.0" 1716 | resolved "https://registry.yarnpkg.com/terser/-/terser-5.24.0.tgz#4ae50302977bca4831ccc7b4fef63a3c04228364" 1717 | integrity sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw== 1718 | dependencies: 1719 | "@jridgewell/source-map" "^0.3.3" 1720 | acorn "^8.8.2" 1721 | commander "^2.20.0" 1722 | source-map-support "~0.5.20" 1723 | 1724 | tmp@^0.2.1: 1725 | version "0.2.1" 1726 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" 1727 | integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== 1728 | dependencies: 1729 | rimraf "^3.0.0" 1730 | 1731 | to-regex-range@^5.0.1: 1732 | version "5.0.1" 1733 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1734 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1735 | dependencies: 1736 | is-number "^7.0.0" 1737 | 1738 | toidentifier@1.0.1: 1739 | version "1.0.1" 1740 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 1741 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 1742 | 1743 | type-is@~1.6.18: 1744 | version "1.6.18" 1745 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 1746 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 1747 | dependencies: 1748 | media-typer "0.3.0" 1749 | mime-types "~2.1.24" 1750 | 1751 | typescript@5.0.4: 1752 | version "5.0.4" 1753 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" 1754 | integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== 1755 | 1756 | ua-parser-js@^0.7.30: 1757 | version "0.7.37" 1758 | resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.37.tgz#e464e66dac2d33a7a1251d7d7a99d6157ec27832" 1759 | integrity sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA== 1760 | 1761 | undici-types@~5.26.4: 1762 | version "5.26.5" 1763 | resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" 1764 | integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== 1765 | 1766 | universalify@^0.1.0: 1767 | version "0.1.2" 1768 | resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" 1769 | integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== 1770 | 1771 | unpipe@1.0.0, unpipe@~1.0.0: 1772 | version "1.0.0" 1773 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 1774 | integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 1775 | 1776 | update-browserslist-db@^1.0.13: 1777 | version "1.0.13" 1778 | resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" 1779 | integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== 1780 | dependencies: 1781 | escalade "^3.1.1" 1782 | picocolors "^1.0.0" 1783 | 1784 | uri-js@^4.2.2: 1785 | version "4.4.1" 1786 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 1787 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1788 | dependencies: 1789 | punycode "^2.1.0" 1790 | 1791 | utils-merge@1.0.1: 1792 | version "1.0.1" 1793 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 1794 | integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== 1795 | 1796 | vary@^1: 1797 | version "1.1.2" 1798 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 1799 | integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== 1800 | 1801 | void-elements@^2.0.0: 1802 | version "2.0.1" 1803 | resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" 1804 | integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== 1805 | 1806 | watchpack@^2.4.0: 1807 | version "2.4.0" 1808 | resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" 1809 | integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== 1810 | dependencies: 1811 | glob-to-regexp "^0.4.1" 1812 | graceful-fs "^4.1.2" 1813 | 1814 | webpack-cli@5.1.0: 1815 | version "5.1.0" 1816 | resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.0.tgz#abc4b1f44b50250f2632d8b8b536cfe2f6257891" 1817 | integrity sha512-a7KRJnCxejFoDpYTOwzm5o21ZXMaNqtRlvS183XzGDUPRdVEzJNImcQokqYZ8BNTnk9DkKiuWxw75+DCCoZ26w== 1818 | dependencies: 1819 | "@discoveryjs/json-ext" "^0.5.0" 1820 | "@webpack-cli/configtest" "^2.1.0" 1821 | "@webpack-cli/info" "^2.0.1" 1822 | "@webpack-cli/serve" "^2.0.3" 1823 | colorette "^2.0.14" 1824 | commander "^10.0.1" 1825 | cross-spawn "^7.0.3" 1826 | envinfo "^7.7.3" 1827 | fastest-levenshtein "^1.0.12" 1828 | import-local "^3.0.2" 1829 | interpret "^3.1.1" 1830 | rechoir "^0.8.0" 1831 | webpack-merge "^5.7.3" 1832 | 1833 | webpack-merge@^4.1.5: 1834 | version "4.2.2" 1835 | resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" 1836 | integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== 1837 | dependencies: 1838 | lodash "^4.17.15" 1839 | 1840 | webpack-merge@^5.7.3: 1841 | version "5.10.0" 1842 | resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" 1843 | integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== 1844 | dependencies: 1845 | clone-deep "^4.0.1" 1846 | flat "^5.0.2" 1847 | wildcard "^2.0.0" 1848 | 1849 | webpack-sources@^3.2.3: 1850 | version "3.2.3" 1851 | resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" 1852 | integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== 1853 | 1854 | webpack@5.82.0: 1855 | version "5.82.0" 1856 | resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.82.0.tgz#3c0d074dec79401db026b4ba0fb23d6333f88e7d" 1857 | integrity sha512-iGNA2fHhnDcV1bONdUu554eZx+XeldsaeQ8T67H6KKHl2nUSwX8Zm7cmzOA46ox/X1ARxf7Bjv8wQ/HsB5fxBg== 1858 | dependencies: 1859 | "@types/eslint-scope" "^3.7.3" 1860 | "@types/estree" "^1.0.0" 1861 | "@webassemblyjs/ast" "^1.11.5" 1862 | "@webassemblyjs/wasm-edit" "^1.11.5" 1863 | "@webassemblyjs/wasm-parser" "^1.11.5" 1864 | acorn "^8.7.1" 1865 | acorn-import-assertions "^1.7.6" 1866 | browserslist "^4.14.5" 1867 | chrome-trace-event "^1.0.2" 1868 | enhanced-resolve "^5.13.0" 1869 | es-module-lexer "^1.2.1" 1870 | eslint-scope "5.1.1" 1871 | events "^3.2.0" 1872 | glob-to-regexp "^0.4.1" 1873 | graceful-fs "^4.2.9" 1874 | json-parse-even-better-errors "^2.3.1" 1875 | loader-runner "^4.2.0" 1876 | mime-types "^2.1.27" 1877 | neo-async "^2.6.2" 1878 | schema-utils "^3.1.2" 1879 | tapable "^2.1.1" 1880 | terser-webpack-plugin "^5.3.7" 1881 | watchpack "^2.4.0" 1882 | webpack-sources "^3.2.3" 1883 | 1884 | which@^1.2.1: 1885 | version "1.3.1" 1886 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 1887 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 1888 | dependencies: 1889 | isexe "^2.0.0" 1890 | 1891 | which@^2.0.1: 1892 | version "2.0.2" 1893 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1894 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1895 | dependencies: 1896 | isexe "^2.0.0" 1897 | 1898 | wildcard@^2.0.0: 1899 | version "2.0.1" 1900 | resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" 1901 | integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== 1902 | 1903 | workerpool@6.2.1: 1904 | version "6.2.1" 1905 | resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" 1906 | integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== 1907 | 1908 | wrap-ansi@^7.0.0: 1909 | version "7.0.0" 1910 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1911 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1912 | dependencies: 1913 | ansi-styles "^4.0.0" 1914 | string-width "^4.1.0" 1915 | strip-ansi "^6.0.0" 1916 | 1917 | wrappy@1: 1918 | version "1.0.2" 1919 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1920 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== 1921 | 1922 | ws@~8.11.0: 1923 | version "8.11.0" 1924 | resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" 1925 | integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== 1926 | 1927 | y18n@^5.0.5: 1928 | version "5.0.8" 1929 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 1930 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 1931 | 1932 | yargs-parser@20.2.4: 1933 | version "20.2.4" 1934 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" 1935 | integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== 1936 | 1937 | yargs-parser@^20.2.2: 1938 | version "20.2.9" 1939 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" 1940 | integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== 1941 | 1942 | yargs-unparser@2.0.0: 1943 | version "2.0.0" 1944 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" 1945 | integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== 1946 | dependencies: 1947 | camelcase "^6.0.0" 1948 | decamelize "^4.0.0" 1949 | flat "^5.0.2" 1950 | is-plain-obj "^2.1.0" 1951 | 1952 | yargs@16.2.0, yargs@^16.1.1: 1953 | version "16.2.0" 1954 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" 1955 | integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== 1956 | dependencies: 1957 | cliui "^7.0.2" 1958 | escalade "^3.1.1" 1959 | get-caller-file "^2.0.5" 1960 | require-directory "^2.1.1" 1961 | string-width "^4.2.0" 1962 | y18n "^5.0.5" 1963 | yargs-parser "^20.2.2" 1964 | 1965 | yocto-queue@^0.1.0: 1966 | version "0.1.0" 1967 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 1968 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 1969 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | includeBuild("build-logic") 3 | repositories { 4 | mavenLocal() 5 | google() 6 | mavenCentral() 7 | gradlePluginPortal() 8 | } 9 | resolutionStrategy { 10 | eachPlugin { 11 | // `kotlinx-atomicfu` is not published to Gradle Plugin Portal 12 | // https://github.com/Kotlin/kotlinx-atomicfu/issues/56 13 | if (requested.id.id == "kotlinx-atomicfu") { 14 | useModule("org.jetbrains.kotlinx:atomicfu-gradle-plugin:${requested.version}") 15 | } 16 | } 17 | } 18 | } 19 | 20 | dependencyResolutionManagement { 21 | repositoriesMode.set(RepositoriesMode.PREFER_PROJECT) 22 | repositories { 23 | mavenLocal() 24 | google() 25 | mavenCentral() 26 | } 27 | } 28 | 29 | rootProject.name = "cacheable" 30 | include(":cacheable-compiler") 31 | include(":cacheable-core") 32 | include(":cacheable-gradle-plugin") 33 | include(":test") 34 | -------------------------------------------------------------------------------- /test/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.KotlinCompile 2 | 3 | plugins { 4 | alias(libs.plugins.kotlin.multiplatform) 5 | id("com.moriatsushi.cacheable") version "0.0.3" 6 | } 7 | 8 | kotlin { 9 | jvm() 10 | js(IR) { 11 | nodejs() 12 | browser() 13 | } 14 | // TODO: Support Kotlin/WASM 15 | /* 16 | @Suppress("OPT_IN_USAGE") 17 | wasmJs { 18 | binaries.executable() 19 | nodejs() 20 | browser() 21 | } 22 | */ 23 | iosX64() 24 | iosArm64() 25 | iosSimulatorArm64() 26 | macosX64() 27 | macosArm64() 28 | watchosArm64() 29 | watchosX64() 30 | watchosSimulatorArm64() 31 | watchosDeviceArm64() 32 | tvosArm64() 33 | tvosX64() 34 | tvosSimulatorArm64() 35 | 36 | mingwX64() 37 | linuxX64() 38 | linuxArm64() 39 | 40 | sourceSets { 41 | val commonMain by getting { 42 | dependencies { 43 | implementation(project(":cacheable-core")) 44 | implementation(libs.kotlinx.coroutines.core) 45 | } 46 | } 47 | 48 | val commonTest by getting { 49 | dependencies { 50 | implementation(kotlin("test")) 51 | implementation(libs.kotlinx.coroutines.test) 52 | } 53 | } 54 | } 55 | } 56 | 57 | tasks.withType(KotlinCompile::class).all { 58 | dependsOn(":cacheable-compiler:publishToMavenLocal") 59 | } 60 | -------------------------------------------------------------------------------- /test/src/commonMain/kotlin/com/moriatsushi/cacheable/test/ClassWithCompanionObject.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import com.moriatsushi.cacheable.Cacheable 4 | 5 | class ClassWithCompanionObject { 6 | @Cacheable 7 | fun cacheableInt(): Int { 8 | count++ 9 | return count 10 | } 11 | 12 | companion object { 13 | private var count = 0 14 | 15 | @Cacheable 16 | fun cacheableInt(): Int { 17 | count++ 18 | return count 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/src/commonMain/kotlin/com/moriatsushi/cacheable/test/CoroutinesClass.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import com.moriatsushi.cacheable.Cacheable 4 | import kotlinx.coroutines.delay 5 | 6 | class CoroutinesClass { 7 | private var count = 0 8 | 9 | @Cacheable 10 | suspend fun cacheableInt(): Int { 11 | delay(100) 12 | count++ 13 | return count 14 | } 15 | 16 | @Cacheable 17 | suspend fun cacheableWithKey(key: String): Int { 18 | delay(100) 19 | count++ 20 | return count 21 | } 22 | 23 | @Cacheable(lock = true) 24 | suspend fun cacheableWithLock(): Int { 25 | delay(100) 26 | count++ 27 | return count 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/src/commonMain/kotlin/com/moriatsushi/cacheable/test/SimpleClass.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import com.moriatsushi.cacheable.Cacheable 4 | 5 | class SimpleClass { 6 | var count = 0 7 | 8 | @Cacheable 9 | fun cacheableInt(): Int { 10 | count++ 11 | return count 12 | } 13 | 14 | @Cacheable 15 | fun cacheableString(): String { 16 | count++ 17 | return count.toString() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/src/commonMain/kotlin/com/moriatsushi/cacheable/test/SimpleEnumClass.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import com.moriatsushi.cacheable.Cacheable 4 | 5 | enum class SimpleEnumClass(initial: Int) { 6 | A(10), 7 | B(20), 8 | ; 9 | 10 | private var count: Int = initial 11 | 12 | @Cacheable 13 | fun cacheableInt(): Int { 14 | count++ 15 | return count 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/src/commonMain/kotlin/com/moriatsushi/cacheable/test/SimpleObject.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import com.moriatsushi.cacheable.Cacheable 4 | 5 | object SimpleObject { 6 | var count = 0 7 | 8 | @Cacheable 9 | fun cacheableInt(): Int { 10 | count++ 11 | return count 12 | } 13 | 14 | @Cacheable 15 | fun cacheableString(): String { 16 | count++ 17 | return count.toString() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/src/commonMain/kotlin/com/moriatsushi/cacheable/test/TopLevelFunction.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import com.moriatsushi.cacheable.Cacheable 4 | 5 | var globalCount = 0 6 | 7 | @Cacheable 8 | fun cacheableInt(): Int { 9 | globalCount++ 10 | return globalCount 11 | } 12 | 13 | @Cacheable 14 | fun cacheableString(): String { 15 | globalCount++ 16 | return globalCount.toString() 17 | } 18 | 19 | @Cacheable 20 | fun cacheableIntWithKey(key: String): Int { 21 | globalCount++ 22 | return globalCount 23 | } 24 | -------------------------------------------------------------------------------- /test/src/commonMain/kotlin/com/moriatsushi/cacheable/test/WithMaxCountClass.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import com.moriatsushi.cacheable.Cacheable 4 | 5 | class WithMaxCountClass { 6 | private var count = 0 7 | 8 | @Cacheable(maxCount = 2) 9 | fun cacheableInt(key: String): Int { 10 | count++ 11 | return count 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/src/commonTest/kotlin/com/moriatsushi/cacheable/test/ClassWithCompanionObjectTest.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import kotlin.test.Test 4 | import kotlin.test.assertEquals 5 | 6 | class ClassWithCompanionObjectTest { 7 | @Test 8 | fun test() { 9 | val target1 = ClassWithCompanionObject() 10 | val int1 = target1.cacheableInt() 11 | assertEquals(1, int1) 12 | val int2 = target1.cacheableInt() 13 | assertEquals(int1, int2) 14 | 15 | val target2 = ClassWithCompanionObject() 16 | val int3 = target2.cacheableInt() 17 | assertEquals(2, int3) 18 | val int4 = target2.cacheableInt() 19 | assertEquals(int3, int4) 20 | 21 | val int5 = ClassWithCompanionObject.cacheableInt() 22 | assertEquals(3, int5) 23 | val int6 = ClassWithCompanionObject.cacheableInt() 24 | assertEquals(int5, int6) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/src/commonTest/kotlin/com/moriatsushi/cacheable/test/CoroutinesClassTest.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import kotlin.test.Test 4 | import kotlin.test.assertEquals 5 | import kotlinx.coroutines.launch 6 | import kotlinx.coroutines.test.runTest 7 | 8 | class CoroutinesClassTest { 9 | @Test 10 | fun test() = runTest { 11 | val target = CoroutinesClass() 12 | val int1 = target.cacheableInt() 13 | assertEquals(1, int1) 14 | val int2 = target.cacheableInt() 15 | assertEquals(int1, int2) 16 | } 17 | 18 | @Test 19 | fun testWithKey() = runTest { 20 | val target = CoroutinesClass() 21 | val int1 = target.cacheableWithKey("key1") 22 | assertEquals(1, int1) 23 | val int2 = target.cacheableWithKey("key1") 24 | assertEquals(int1, int2) 25 | 26 | val int3 = target.cacheableWithKey("key2") 27 | assertEquals(2, int3) 28 | val int4 = target.cacheableWithKey("key2") 29 | assertEquals(int3, int4) 30 | } 31 | 32 | @Test 33 | fun testWithLock() = runTest { 34 | val target = CoroutinesClass() 35 | 36 | launch { 37 | val int1 = target.cacheableWithLock() 38 | assertEquals(1, int1) 39 | } 40 | launch { 41 | val int2 = target.cacheableWithLock() 42 | assertEquals(1, int2) 43 | } 44 | } 45 | 46 | @Test 47 | fun testWithoutLock() = runTest { 48 | val target = CoroutinesClass() 49 | 50 | launch { 51 | val int1 = target.cacheableInt() 52 | assertEquals(1, int1) 53 | } 54 | launch { 55 | val int2 = target.cacheableInt() 56 | assertEquals(2, int2) 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /test/src/commonTest/kotlin/com/moriatsushi/cacheable/test/FakeTimeProvider.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import com.moriatsushi.cacheable.CacheableTimeProvider 4 | 5 | class FakeTimeProvider : CacheableTimeProvider { 6 | override var currentEpochMillis: Long = 0 7 | } 8 | -------------------------------------------------------------------------------- /test/src/commonTest/kotlin/com/moriatsushi/cacheable/test/SimpleClassTest.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import kotlin.test.Test 4 | import kotlin.test.assertEquals 5 | 6 | class SimpleClassTest { 7 | @Test 8 | fun testCacheable() { 9 | val target = SimpleClass() 10 | val int1 = target.cacheableInt() 11 | assertEquals(1, int1) 12 | val int2 = target.cacheableInt() 13 | assertEquals(int1, int2) 14 | 15 | val string1 = target.cacheableString() 16 | assertEquals("2", string1) 17 | val string2 = target.cacheableString() 18 | assertEquals(string1, string2) 19 | } 20 | 21 | @Test 22 | fun testMultipleInstance() { 23 | val target1 = SimpleClass() 24 | target1.count = 2 25 | val int1 = target1.cacheableInt() 26 | assertEquals(3, int1) 27 | 28 | val target2 = SimpleClass() 29 | target2.count = 4 30 | val int2 = target2.cacheableInt() 31 | assertEquals(5, int2) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/src/commonTest/kotlin/com/moriatsushi/cacheable/test/SimpleEnumClassTest.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import kotlin.test.Test 4 | import kotlin.test.assertEquals 5 | 6 | class SimpleEnumClassTest { 7 | @Test 8 | fun test() { 9 | val int1 = SimpleEnumClass.A.cacheableInt() 10 | assertEquals(11, int1) 11 | val int2 = SimpleEnumClass.A.cacheableInt() 12 | assertEquals(int1, int2) 13 | 14 | val int3 = SimpleEnumClass.B.cacheableInt() 15 | assertEquals(21, int3) 16 | val int4 = SimpleEnumClass.B.cacheableInt() 17 | assertEquals(int3, int4) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/src/commonTest/kotlin/com/moriatsushi/cacheable/test/SimpleObjectTest.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import kotlin.test.Test 4 | import kotlin.test.assertEquals 5 | 6 | class SimpleObjectTest { 7 | @Test 8 | fun testCacheable() { 9 | val int1 = SimpleObject.cacheableInt() 10 | assertEquals(1, int1) 11 | val int2 = SimpleObject.cacheableInt() 12 | assertEquals(int1, int2) 13 | 14 | val string1 = SimpleObject.cacheableString() 15 | assertEquals("2", string1) 16 | val string2 = SimpleObject.cacheableString() 17 | assertEquals(string1, string2) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/src/commonTest/kotlin/com/moriatsushi/cacheable/test/TopLevelFunctionTest.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import kotlin.test.Test 4 | import kotlin.test.assertEquals 5 | 6 | class TopLevelFunctionTest { 7 | @Test 8 | fun test() { 9 | globalCount = 0 10 | 11 | val int1 = cacheableInt() 12 | assertEquals(1, int1) 13 | val int2 = cacheableInt() 14 | assertEquals(int1, int2) 15 | 16 | val string1 = cacheableString() 17 | assertEquals("2", string1) 18 | val string2 = cacheableString() 19 | assertEquals(string1, string2) 20 | } 21 | 22 | @Test 23 | fun testWithKey() { 24 | globalCount = 0 25 | 26 | val intForKeyA1 = cacheableIntWithKey("key-a") 27 | assertEquals(1, intForKeyA1) 28 | val intForKeyB1 = cacheableIntWithKey("key-b") 29 | assertEquals(2, intForKeyB1) 30 | 31 | val intForKeyA2 = cacheableIntWithKey("key-a") 32 | assertEquals(1, intForKeyA2) 33 | val intForKeyB2 = cacheableIntWithKey("key-b") 34 | assertEquals(2, intForKeyB2) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/src/commonTest/kotlin/com/moriatsushi/cacheable/test/WithMaxCountClassTest.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import com.moriatsushi.cacheable.CacheableConfiguration 4 | import kotlin.test.AfterTest 5 | import kotlin.test.BeforeTest 6 | import kotlin.test.Test 7 | import kotlin.test.assertEquals 8 | 9 | class WithMaxCountClassTest { 10 | private val fakeTimeProvider = FakeTimeProvider() 11 | 12 | @BeforeTest 13 | fun setUp() { 14 | CacheableConfiguration.timeProvider = fakeTimeProvider 15 | } 16 | 17 | @AfterTest 18 | fun tearDown() { 19 | CacheableConfiguration.resetTimeProvider() 20 | } 21 | 22 | @Test 23 | fun test() { 24 | val target = WithMaxCountClass() 25 | 26 | fakeTimeProvider.currentEpochMillis = 0 27 | val result1 = target.cacheableInt("key1") 28 | assertEquals(1, result1) 29 | 30 | fakeTimeProvider.currentEpochMillis = 1 31 | val result2 = target.cacheableInt("key2") 32 | assertEquals(2, result2) 33 | 34 | fakeTimeProvider.currentEpochMillis = 2 35 | val result3 = target.cacheableInt("key1") 36 | assertEquals(1, result3) 37 | 38 | fakeTimeProvider.currentEpochMillis = 3 39 | val result4 = target.cacheableInt("key3") 40 | assertEquals(3, result4) 41 | 42 | fakeTimeProvider.currentEpochMillis = 4 43 | val result5 = target.cacheableInt("key1") 44 | assertEquals(1, result5) 45 | 46 | fakeTimeProvider.currentEpochMillis = 5 47 | val result6 = target.cacheableInt("key2") 48 | assertEquals(4, result6) 49 | 50 | fakeTimeProvider.currentEpochMillis = 6 51 | val result7 = target.cacheableInt("key3") 52 | assertEquals(5, result7) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /test/src/jvmMain/kotlin/com/moriatsushi/cacheable/test/MultiThreadClass.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import com.moriatsushi.cacheable.Cacheable 4 | 5 | class MultiThreadClass { 6 | private var count = 0 7 | 8 | @Cacheable(lock = true) 9 | fun withLock(): Int { 10 | Thread.sleep(100) 11 | count++ 12 | return count 13 | } 14 | 15 | @Cacheable 16 | fun withoutLock(): Int { 17 | Thread.sleep(30) 18 | count++ 19 | return count 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/src/jvmTest/kotlin/com/moriatsushi/cacheable/test/MultiThreadClassTest.kt: -------------------------------------------------------------------------------- 1 | package com.moriatsushi.cacheable.test 2 | 3 | import kotlin.test.assertEquals 4 | import kotlinx.coroutines.Dispatchers 5 | import kotlinx.coroutines.delay 6 | import kotlinx.coroutines.launch 7 | import kotlinx.coroutines.runBlocking 8 | import org.junit.Test 9 | 10 | class MultiThreadClassTest { 11 | @Test 12 | fun testWithLock() { 13 | runBlocking { 14 | val multiThreadClass = MultiThreadClass() 15 | launch(Dispatchers.Default) { 16 | assertEquals(1, multiThreadClass.withLock()) 17 | } 18 | launch(Dispatchers.Default) { 19 | assertEquals(1, multiThreadClass.withLock()) 20 | } 21 | } 22 | } 23 | 24 | @Test 25 | fun testWithoutLock() { 26 | runBlocking { 27 | val multiThreadClass = MultiThreadClass() 28 | launch(Dispatchers.Default) { 29 | assertEquals(1, multiThreadClass.withoutLock()) 30 | } 31 | delay(10) 32 | launch(Dispatchers.Default) { 33 | assertEquals(2, multiThreadClass.withoutLock()) 34 | } 35 | } 36 | } 37 | } 38 | --------------------------------------------------------------------------------