diff --git a/.gitignore b/.gitignore index e901d0dd..50022365 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,4 @@ $RECYCLE.BIN/ Thumbs.db UserInterfaceState.xcuserstate -src/assets/libs/*.browserify.js +src/assets/protocol_modules/ diff --git a/Dockerfile b/Dockerfile index a6921748..f9294597 100755 --- a/Dockerfile +++ b/Dockerfile @@ -34,6 +34,7 @@ COPY package.json /app COPY yarn.lock /app COPY apply-diagnostic-modules.js /app COPY fix-qrscanner-gradle.js /app +COPY copy-builtin-modules.js /app RUN yarn install-test-dependencies diff --git a/android/app/build.gradle b/android/app/build.gradle index 6fdebcdd..f76e402b 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -81,6 +81,10 @@ dependencies { def saplingVersion = "0.0.7" implementation "com.github.airgap-it:airgap-sapling:$saplingVersion" + + implementation "androidx.javascriptengine:javascriptengine:1.0.0-alpha03" + implementation 'com.google.guava:listenablefuture:1.0' + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-guava:$coroutinesVersion" } diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle index ac026f32..db71306d 100644 --- a/android/app/capacitor.build.gradle +++ b/android/app/capacitor.build.gradle @@ -2,8 +2,8 @@ android { compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } } @@ -15,6 +15,7 @@ dependencies { implementation project(':capacitor-filesystem') implementation project(':capacitor-splash-screen') implementation project(':capacitor-status-bar') + implementation project(':capawesome-capacitor-file-picker') implementation "com.android.support:support-v4:26.+" implementation "com.android.support:appcompat-v7:26.+" } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index dfc145a6..d4974cae 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,11 @@ - + + + + { + fun listModules(): List + + fun readModuleSources(module: M): Sequence + fun readModuleManifest(module: String): ByteArray +} + +private const val MANIFEST_FILENAME = "manifest.json" + +class FileExplorer private constructor( + private val context: Context, + private val assetsExplorer: AssetsExplorer, + private val filesExplorer: FilesExplorer, +) : StaticSourcesExplorer by assetsExplorer { + constructor(context: Context) : this(context, AssetsExplorer(context), FilesExplorer(context)) + + fun loadAssetModules(): List = loadModules(assetsExplorer, JSModule::Asset) + + fun loadInstalledModules(): List = loadModules(filesExplorer, JSModule::Installed) + + fun loadInstalledModule(identifier: String): JSModule { + val manifest = JSObject(filesExplorer.readModuleManifest(identifier).decodeToString()) + + return loadModule(identifier, manifest, JSModule::Installed) + } + + fun loadPreviewModule(path: String, directory: Directory): JSModule { + val moduleDir = File(context.getDirectory(directory), path) + val manifest = JSObject(File(moduleDir, MANIFEST_FILENAME).readBytes().decodeToString()) + + return loadModule(moduleDir.name, manifest) { identifier, namespace, preferredEnvironment, paths -> + JSModule.Preview( + identifier, + namespace, + preferredEnvironment, + paths, + moduleDir.absolutePath, + ) + } + } + + fun readModuleSources(module: JSModule): Sequence = + when (module) { + is JSModule.Asset -> assetsExplorer.readModuleSources(module) + is JSModule.Installed -> filesExplorer.readModuleSources(module) + is JSModule.Preview -> module.sources.asSequence().map { File(module.path, it).readBytes() } + } + + fun readModuleManifest(module: JSModule): ByteArray = + when (module) { + is JSModule.Asset -> assetsExplorer.readModuleManifest(module.identifier) + is JSModule.Installed -> filesExplorer.readModuleManifest(module.identifier) + is JSModule.Preview -> File(module.path, MANIFEST_FILENAME).readBytes() + } + + private fun loadModules( + explorer: DynamicSourcesExplorer, + constructor: (identifier: String, namespace: String?, preferredEnvironment: JSEnvironment.Type, paths: List) -> T, + ): List = explorer.listModules().map { module -> + val manifest = JSObject(explorer.readModuleManifest(module).decodeToString()) + loadModule(module, manifest, constructor) + } + + private fun loadModule( + identifier: String, + manifest: JSObject, + constructor: (identifier: String, namespace: String?, preferredEnvironment: JSEnvironment.Type, paths: List) -> T, + ): T { + val namespace = manifest.getJSObject("src")?.getString("namespace") + val preferredEnvironment = manifest.getJSObject("jsenv")?.getString("android")?.let { JSEnvironment.Type.fromString(it) } ?: JSEnvironment.Type.JavaScriptEngine + val sources = buildList { + val include = manifest.getJSONArray("include") + for (i in 0 until include.length()) { + val source = include.getString(i).takeIf { it.endsWith(".js") } ?: continue + add(source.trimStart('/')) + } + } + + return constructor(identifier, namespace, preferredEnvironment, sources) + } +} + +private class AssetsExplorer(private val context: Context) : StaticSourcesExplorer, DynamicSourcesExplorer { + override fun readJavaScriptEngineUtils(): ByteArray = context.assets.readBytes(JAVA_SCRIPT_ENGINE_UTILS) + override fun readIsolatedModulesScript(): ByteArray = context.assets.readBytes(SCRIPT) + + override fun listModules(): List = context.assets.list(MODULES_DIR)?.toList() ?: emptyList() + + override fun readModuleSources(module: JSModule.Asset): Sequence = + module.sources.asSequence().map { context.assets.readBytes(modulePath(module.identifier, it))} + override fun readModuleManifest(module: String): ByteArray = context.assets.readBytes(modulePath(module, MANIFEST_FILENAME)) + + private fun modulePath(module: String, path: String): String = + "${MODULES_DIR}/${module.trimStart('/')}/${path.trimStart('/')}" + + companion object { + private const val SCRIPT = "public/assets/native/isolated_modules/isolated-modules.script.js" + private const val JAVA_SCRIPT_ENGINE_UTILS = "public/assets/native/isolated_modules/isolated-modules.js-engine-android.js" + + private const val MODULES_DIR = "public/assets/protocol_modules" + } +} + +private class FilesExplorer(private val context: Context) : DynamicSourcesExplorer { + private val modulesDir: File + get() = File(context.filesDir, MODULES_DIR) + + override fun listModules(): List = modulesDir.list()?.toList() ?: emptyList() + + override fun readModuleSources(module: JSModule.Installed): Sequence = + module.sources.asSequence().map { File(modulesDir, modulePath(module.identifier, it)).readBytes() } + override fun readModuleManifest(module: String): ByteArray = File(modulesDir, modulePath(module, MANIFEST_FILENAME)).readBytes() + + private fun modulePath(module: String, path: String): String = + "${module.trimStart('/')}/${path.trimStart('/')}" + + companion object { + private const val MODULES_DIR = "protocol_modules" + } +} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/IsolatedModules.kt b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/IsolatedModules.kt new file mode 100644 index 00000000..ed1c7ac5 --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/IsolatedModules.kt @@ -0,0 +1,157 @@ +package it.airgap.vault.plugin.isolatedmodules + +import androidx.lifecycle.lifecycleScope +import com.getcapacitor.JSArray +import com.getcapacitor.JSObject +import com.getcapacitor.Plugin +import com.getcapacitor.PluginCall +import com.getcapacitor.PluginMethod +import com.getcapacitor.annotation.CapacitorPlugin +import it.airgap.vault.plugin.isolatedmodules.js.* +import it.airgap.vault.util.* +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.launch + +@CapacitorPlugin +class IsolatedModules : Plugin() { + private val jsEvaluator: Deferred = ExecutableDeferred { JSEvaluator(context, fileExplorer) } + private val fileExplorer: FileExplorer by lazy { FileExplorer(context) } + + @PluginMethod + fun previewModule(call: PluginCall) { + call.executeCatching { + assertReceived(Param.PATH, Param.DIRECTORY) + + activity.lifecycleScope.launch { + executeCatching { + val module = fileExplorer.loadPreviewModule(path, directory) + val manifest = fileExplorer.readModuleManifest(module) + val moduleJson = jsEvaluator.await().evaluatePreviewModule(module) + + resolve( + JSObject( + """ + { + "module": $moduleJson, + "manifest": ${JSObject(manifest.decodeToString())} + } + """.trimIndent() + ) + ) + } + } + } + } + + @PluginMethod + fun registerModule(call: PluginCall) { + call.executeCatching { + assertReceived(Param.IDENTIFIER, Param.PROTOCOL_IDENTIFIERS) + + activity.lifecycleScope.launch { + executeCatching { + val module = fileExplorer.loadInstalledModule(identifier) + jsEvaluator.await().registerModule(module, protocolIdentifiers) + + resolve() + } + } + } + } + + @PluginMethod + fun loadModules(call: PluginCall) { + activity.lifecycleScope.launch { + call.executeCatching { + val modules = fileExplorer.loadAssetModules() + fileExplorer.loadInstalledModules() + + resolve(jsEvaluator.await().evaluateLoadModules(modules, protocolType)) + } + } + } + + @PluginMethod + fun callMethod(call: PluginCall) { + call.executeCatching { + assertReceived(Param.TARGET, Param.METHOD) + + activity.lifecycleScope.launch { + executeCatching { + val value = when (target) { + JSCallMethodTarget.OfflineProtocol -> { + assertReceived(Param.PROTOCOL_IDENTIFIER) + jsEvaluator.await().evaluateCallOfflineProtocolMethod(method, args, protocolIdentifier) + } + JSCallMethodTarget.OnlineProtocol -> { + assertReceived(Param.PROTOCOL_IDENTIFIER) + jsEvaluator.await().evaluateCallOnlineProtocolMethod(method, args, protocolIdentifier, networkId) + } + JSCallMethodTarget.BlockExplorer -> { + assertReceived(Param.PROTOCOL_IDENTIFIER) + jsEvaluator.await().evaluateCallBlockExplorerMethod(method, args, protocolIdentifier, networkId) + } + JSCallMethodTarget.V3SerializerCompanion -> { + assertReceived(Param.MODULE_IDENTIFIER) + jsEvaluator.await().evaluateCallV3SerializerCompanionMethod(method, args, moduleIdentifier) + } + } + resolve(value) + } + } + } + } + + override fun handleOnDestroy() { + super.handleOnDestroy() + activity.lifecycleScope.launch { + jsEvaluator.await().destroy() + } + } + + private val PluginCall.path: String + get() = getString(Param.PATH)!! + + private val PluginCall.directory: Directory + get() = getString(Param.DIRECTORY)?.let { Directory.fromString(it) }!! + + private val PluginCall.identifier: String + get() = getString(Param.IDENTIFIER)!! + + private val PluginCall.protocolIdentifiers: List + get() = getArray(Param.PROTOCOL_IDENTIFIERS).toList() + + private val PluginCall.protocolType: JSProtocolType? + get() = getString(Param.PROTOCOL_TYPE)?.let { JSProtocolType.fromString(it) } + + private val PluginCall.target: JSCallMethodTarget + get() = getString(Param.TARGET)?.let { JSCallMethodTarget.fromString(it) }!! + + private val PluginCall.method: String + get() = getString(Param.METHOD)!! + + private val PluginCall.args: JSArray? + get() = getArray(Param.ARGS, null) + + private val PluginCall.protocolIdentifier: String + get() = getString(Param.PROTOCOL_IDENTIFIER)!! + + private val PluginCall.moduleIdentifier: String + get() = getString(Param.MODULE_IDENTIFIER)!! + + private val PluginCall.networkId: String? + get() = getString(Param.NETWORK_ID) + + private object Param { + const val PATH = "path" + const val DIRECTORY = "directory" + const val IDENTIFIER = "identifier" + const val PROTOCOL_IDENTIFIERS = "protocolIdentifiers" + const val PROTOCOL_TYPE = "protocolType" + const val TARGET = "target" + const val METHOD = "method" + const val ARGS = "args" + const val PROTOCOL_IDENTIFIER = "protocolIdentifier" + const val MODULE_IDENTIFIER = "moduleIdentifier" + const val NETWORK_ID = "networkId" + } +} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/IsolatedProtocol.kt b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/IsolatedProtocol.kt deleted file mode 100644 index 87c7e277..00000000 --- a/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/IsolatedProtocol.kt +++ /dev/null @@ -1,143 +0,0 @@ -package it.airgap.vault.plugin.isolatedmodules - -import android.webkit.WebView -import androidx.lifecycle.lifecycleScope -import com.getcapacitor.* -import com.getcapacitor.annotation.CapacitorPlugin -import it.airgap.vault.util.JSCompletableDeferred -import it.airgap.vault.util.JSUndefined -import it.airgap.vault.util.addJavascriptInterface -import it.airgap.vault.util.assertReceived -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -@CapacitorPlugin -class IsolatedProtocol : Plugin() { - - @PluginMethod - fun getField(call: PluginCall) { - with(call) { - assertReceived(Param.IDENTIFIER, Param.KEY) - - activity.lifecycleScope.launch(Dispatchers.Default) { - call.resolve(getField(identifier, options, key)) - } - } - } - - @PluginMethod - fun callMethod(call: PluginCall) { - with(call) { - assertReceived(Param.IDENTIFIER, Param.KEY) - - activity.lifecycleScope.launch(Dispatchers.Default) { - call.resolve(callMethod(identifier, options, key, args?.replaceNullWithUndefined())) - } - } - } - - private suspend fun getField(identifier: String, options: JSObject?, key: String): Result = - spawnCoinlibWebView(identifier, options, JSProtocolAction.GetField, """ - var __platform__field = '$key' - """.trimIndent()) - - private suspend fun callMethod(identifier: String, options: JSObject?, key: String, args: JSArray?): Result { - val args = args?.toString() ?: "[]" - - return spawnCoinlibWebView(identifier, options, JSProtocolAction.CallMethod, """ - var __platform__method = '$key' - var __platform__args = $args - """.trimIndent()) - } - - private suspend fun spawnCoinlibWebView( - identifier: String, - options: JSObject?, - action: JSProtocolAction, - script: String? = null, - ): Result { - val webViewContext = Dispatchers.Main - - val resultDeferred = JSCompletableDeferred("resultDeferred") - val webView = withContext(webViewContext) { - WebView(context).apply { - settings.javaScriptEnabled = true - addJavascriptInterface(resultDeferred) - } - } - - val html = """ - - - - """.trimIndent() - - withContext(webViewContext) { - webView.loadDataWithBaseURL( - ASSETS_PATH, - html, - "text/html", - "utf-8", - null, - ) - } - - return resultDeferred.await() - } - - private fun JSObject?.orUndefined(): Any = this ?: JSUndefined - - private fun JSArray.replaceNullWithUndefined(): JSArray = - JSArray(toList().map { if (it == JSObject.NULL) JSUndefined else it }) - - private fun PluginCall.resolve(result: Result) { - result.onSuccess { resolve(it) } - result.onFailure { errorCallback(it.message) } - } - - private val PluginCall.identifier: String - get() = getString(Param.IDENTIFIER)!! - - private val PluginCall.options: JSObject? - get() = getObject(Param.OPTIONS, null) - - private val PluginCall.key: String - get() = getString(Param.KEY)!! - - private val PluginCall.args: JSArray? - get() = getArray(Param.ARGS, null) - - private enum class JSProtocolAction(val value: String) { - GetField("getField"), - CallMethod("callMethod") - } - - private object Param { - const val IDENTIFIER = "identifier" - const val OPTIONS = "options" - const val KEY = "key" - const val ARGS = "args" - } - - companion object { - private const val ASSETS_PATH: String = "file:///android_asset" - - private const val COINLIB_SOURCE: String = "public/assets/libs/airgap-coin-lib.browserify.js" - private const val COMMON_SOURCE: String = "public/assets/native/isolated_modules/protocol_common.js" - } -} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/JSEvaluator.kt b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/JSEvaluator.kt new file mode 100644 index 00000000..ae31f440 --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/JSEvaluator.kt @@ -0,0 +1,136 @@ +package it.airgap.vault.plugin.isolatedmodules.js + +import android.content.Context +import android.os.Build +import com.getcapacitor.JSArray +import com.getcapacitor.JSObject +import it.airgap.vault.plugin.isolatedmodules.FileExplorer +import it.airgap.vault.plugin.isolatedmodules.js.environment.JSEnvironment +import it.airgap.vault.plugin.isolatedmodules.js.environment.JavaScriptEngineEnvironment +import it.airgap.vault.plugin.isolatedmodules.js.environment.WebViewEnvironment +import it.airgap.vault.util.* +import kotlinx.coroutines.* +import java.util.* + +class JSEvaluator constructor( + private val defaultEnvironment: JSEnvironment, + private val environments: Map +) { + private val modules: MutableMap = mutableMapOf() + + fun registerModule(module: JSModule, protocolIdentifiers: List) { + module.registerFor(protocolIdentifiers) + } + + suspend fun evaluatePreviewModule(module: JSModule): JSObject = + module.environment.run(module, JSModuleAction.Load(null)).also { + module.appendType(it) + } + + suspend fun evaluateLoadModules(modules: List, protocolType: JSProtocolType?): JSObject { + val modulesJson = modules.asyncMap { module -> + module.environment.run(module, JSModuleAction.Load(protocolType)).also { + module.appendType(it) + module.registerFor(it) + } + } + + return JSObject(""" + { + "modules": $modulesJson + } + """.trimIndent()) + } + + suspend fun evaluateCallOfflineProtocolMethod( + name: String, + args: JSArray?, + protocolIdentifier: String, + ): JSObject { + val module = modules[protocolIdentifier] ?: failWithModuleForProtocolNotFound(protocolIdentifier) + return module.environment.run(module, JSModuleAction.CallMethod.OfflineProtocol(name, args, protocolIdentifier)) + } + + suspend fun evaluateCallOnlineProtocolMethod( + name: String, + args: JSArray?, + protocolIdentifier: String, + networkId: String?, + ): JSObject { + val module = modules[protocolIdentifier] ?: failWithModuleForProtocolNotFound(protocolIdentifier) + return module.environment.run(module, JSModuleAction.CallMethod.OnlineProtocol(name, args, protocolIdentifier, networkId)) + } + + suspend fun evaluateCallBlockExplorerMethod( + name: String, + args: JSArray?, + protocolIdentifier: String, + networkId: String?, + ): JSObject { + val module = modules[protocolIdentifier] ?: failWithModuleForProtocolNotFound(protocolIdentifier) + return module.environment.run(module, JSModuleAction.CallMethod.BlockExplorer(name, args, protocolIdentifier, networkId)) + } + + suspend fun evaluateCallV3SerializerCompanionMethod( + name: String, + args: JSArray?, + moduleIdentifier: String, + ): JSObject { + val module = modules[moduleIdentifier] ?: failWithModuleNotFound(moduleIdentifier) + return module.environment.run(module, JSModuleAction.CallMethod.V3SerializerCompanion(name, args)) + } + + + suspend fun destroy() { + environments.values.forEach { it?.destroy() } + } + + private val JSModule.environment: JSEnvironment + get() = environments[preferredEnvironment] ?: defaultEnvironment + + private fun JSModule.appendType(json: JSObject) { + val type = when (this) { + is JSModule.Asset -> "static" + is JSModule.Installed, is JSModule.Preview -> "dynamic" + } + + json.put("type", type) + } + + private fun JSModule.registerFor(json: JSObject) { + val protocols = json.getJSONArray("protocols") + val protocolIdentifiers = buildList { + for (i in 0 until protocols.length()) { + val protocol = protocols.getJSONObject(i) + add(protocol.getString("identifier")) + } + } + + registerFor(protocolIdentifiers) + } + + private fun JSModule.registerFor(protocolIdentifiers: List) { + modules[identifier] = this + protocolIdentifiers.forEach { modules[it] = this } + } + + @Throws(IllegalStateException::class) + private fun failWithModuleForProtocolNotFound(protocolIdentifier: String): Nothing = throw IllegalStateException("Module for protocol $protocolIdentifier could not be found.") + + @Throws(IllegalStateException::class) + private fun failWithModuleNotFound(moduleIdentifier: String): Nothing = throw IllegalStateException("Module $moduleIdentifier could not be found.") +} + +suspend fun JSEvaluator(context: Context, fileExplorer: FileExplorer): JSEvaluator { + val webViewEnvironment = WebViewEnvironment(context, fileExplorer) + val javaScriptEngineEnvironment = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) JavaScriptEngineEnvironment(context, fileExplorer).takeIf { it.isSupported() } + else null + + val environments = mapOf( + JSEnvironment.Type.WebView to webViewEnvironment, + JSEnvironment.Type.JavaScriptEngine to javaScriptEngineEnvironment, + ) + + return JSEvaluator(webViewEnvironment, environments) +} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/JSModule.kt b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/JSModule.kt new file mode 100644 index 00000000..8f8c948c --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/JSModule.kt @@ -0,0 +1,145 @@ +package it.airgap.vault.plugin.isolatedmodules.js + +import com.getcapacitor.JSArray +import com.getcapacitor.JSObject +import it.airgap.vault.plugin.isolatedmodules.js.environment.JSEnvironment +import it.airgap.vault.util.JSUndefined +import it.airgap.vault.util.assign +import it.airgap.vault.util.toJson +import java.util.* + +sealed interface JSModule { + val identifier: String + val namespace: String? + val preferredEnvironment: JSEnvironment.Type + val sources: List + + data class Asset( + override val identifier: String, + override val namespace: String?, + override val preferredEnvironment: JSEnvironment.Type, + override val sources: List, + ) : JSModule + + data class Installed( + override val identifier: String, + override val namespace: String?, + override val preferredEnvironment: JSEnvironment.Type, + override val sources: List, + ) : JSModule + + data class Preview( + override val identifier: String, + override val namespace: String?, + override val preferredEnvironment: JSEnvironment.Type, + override val sources: List, + val path: String, + ) : JSModule +} + +enum class JSProtocolType { + Offline, Online, Full; + + override fun toString(): String = name.replaceFirstChar { it.lowercase(Locale.getDefault()) } + + companion object { + fun fromString(value: String): JSProtocolType? = values().find { it.name.lowercase() == value.lowercase() } + } +} + +enum class JSCallMethodTarget { + OfflineProtocol, OnlineProtocol, BlockExplorer, V3SerializerCompanion; + + override fun toString(): String = name.replaceFirstChar { it.lowercase(Locale.getDefault()) } + + companion object { + fun fromString(value: String): JSCallMethodTarget? = values().find { it.name.lowercase() == value.lowercase() } + } +} + +sealed interface JSModuleAction { + fun toJson(): String + + data class Load(val protocolType: JSProtocolType?) : JSModuleAction { + override fun toJson(): String = JSObject(""" + { + "type": "$TYPE", + "protocolType": ${protocolType?.toString().toJson()} + } + """.trimIndent()).toString() + + companion object { + private const val TYPE = "load" + } + } + + sealed class CallMethod(val target: JSCallMethodTarget, private val partial: JSObject) : + JSModuleAction { + abstract val name: String + abstract val args: JSArray? + + override fun toJson(): String { + val args = args?.toString() ?: "[]" + + return JSObject(""" + { + "type": "$TYPE", + "target": "$target", + "method": "$name", + "args": $args + } + """.trimIndent()) + .assign(partial) + .toString() + } + + data class OfflineProtocol( + override val name: String, + override val args: JSArray?, + val protocolIdentifier: String, + ) : CallMethod( + JSCallMethodTarget.OfflineProtocol, JSObject(""" + { + protocolIdentifier: "$protocolIdentifier" + } + """.trimIndent()) + ) + + data class OnlineProtocol( + override val name: String, + override val args: JSArray?, + val protocolIdentifier: String, + val networkId: String?, + ) : CallMethod( + JSCallMethodTarget.OnlineProtocol, JSObject(""" + { + protocolIdentifier: "$protocolIdentifier", + networkId: ${networkId.toJson()} + } + """.trimIndent()) + ) + + data class BlockExplorer( + override val name: String, + override val args: JSArray?, + val protocolIdentifier: String, + val networkId: String?, + ) : CallMethod( + JSCallMethodTarget.BlockExplorer, JSObject(""" + { + protocolIdentifier: "$protocolIdentifier", + networkId: ${networkId.toJson()} + } + """.trimIndent()) + ) + + data class V3SerializerCompanion( + override val name: String, + override val args: JSArray? + ) : CallMethod(JSCallMethodTarget.V3SerializerCompanion, JSObject("{}")) + + companion object { + private const val TYPE = "callMethod" + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/environment/JSEnvironment.kt b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/environment/JSEnvironment.kt new file mode 100644 index 00000000..3427934e --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/environment/JSEnvironment.kt @@ -0,0 +1,21 @@ +package it.airgap.vault.plugin.isolatedmodules.js.environment + +import com.getcapacitor.JSObject +import it.airgap.vault.plugin.isolatedmodules.js.JSModule +import it.airgap.vault.plugin.isolatedmodules.js.JSModuleAction +import it.airgap.vault.util.JSException + +interface JSEnvironment { + suspend fun isSupported(): Boolean + @Throws(JSException::class) + suspend fun run(module: JSModule, action: JSModuleAction): JSObject + suspend fun destroy() + + enum class Type { + WebView, JavaScriptEngine; + + companion object { + fun fromString(value: String): Type? = values().find { it.name.lowercase() == value.lowercase() } + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/environment/JavaScriptEngineEnvironment.kt b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/environment/JavaScriptEngineEnvironment.kt new file mode 100644 index 00000000..d4bd205f --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/environment/JavaScriptEngineEnvironment.kt @@ -0,0 +1,98 @@ +package it.airgap.vault.plugin.isolatedmodules.js.environment + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.AssetManager +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.javascriptengine.IsolateStartupParameters +import androidx.javascriptengine.JavaScriptIsolate +import androidx.javascriptengine.JavaScriptSandbox +import com.getcapacitor.JSObject +import it.airgap.vault.plugin.isolatedmodules.FileExplorer +import it.airgap.vault.plugin.isolatedmodules.js.* +import it.airgap.vault.util.JSException +import it.airgap.vault.util.readBytes +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.guava.asDeferred +import kotlinx.coroutines.withContext + +@RequiresApi(Build.VERSION_CODES.O) +class JavaScriptEngineEnvironment( + private val context: Context, + private val fileExplorer: FileExplorer, +) : JSEnvironment { + private val sandbox: Deferred = JavaScriptSandbox.createConnectedInstanceAsync(context).asDeferred() + private val isolates: MutableMap = mutableMapOf() + + override suspend fun isSupported(): Boolean = + JavaScriptSandbox.isSupported() && sandbox.await().let { + it.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROVIDE_CONSUME_ARRAY_BUFFER) + && it.isFeatureSupported(JavaScriptSandbox.JS_FEATURE_PROMISE_RETURN) + } + + @Throws(JSException::class) + override suspend fun run(module: JSModule, action: JSModuleAction): JSObject = withContext(Dispatchers.Default) { + useIsolatedModule(module) { jsIsolate -> + val namespace = module.namespace?.let { "global.$it" } ?: "global" + + val script = """ + new Promise((resolve, reject) => { + execute( + $namespace, + '${module.identifier}', + ${action.toJson()}, + function (result) { + resolve(JSON.stringify(result)); + }, + function (error) { + reject(JSON.stringify({ error })); + } + ); + }) + """.trimIndent() + + val result = jsIsolate.evaluateJavaScriptAsync(script).asDeferred().await() + val jsObject = JSObject(result) + jsObject.getString("error")?.let { error -> throw JSException(error) } + + jsObject + } + } + + override suspend fun destroy() { + isolates.values.forEach { it.close() } + sandbox.await().close() + } + + private suspend inline fun useIsolatedModule(module: JSModule, block: (JavaScriptIsolate) -> R): R { + val jsIsolate = isolates.getOrPut(module.identifier) { + sandbox.await().createIsolate(IsolateStartupParameters()).also { + listOf( + it.evaluateJavaScriptAsync(fileExplorer.readJavaScriptEngineUtils().decodeToString()).asDeferred(), + it.evaluateJavaScriptAsync(fileExplorer.readIsolatedModulesScript().decodeToString()).asDeferred(), + ).awaitAll() + it.loadModule(module) + } + } + + return block(jsIsolate) + } + + @SuppressLint("RequiresFeature" /* checked in JavaScriptEngineEnvironment#isSupported */) + private suspend fun JavaScriptIsolate.loadModule(module: JSModule) { + val sources = fileExplorer.readModuleSources(module) + sources.forEachIndexed { idx, source -> + val scriptId = "${module.identifier}-$idx-script" + provideNamedData(scriptId, source) + evaluateJavaScriptAsync(""" + android.consumeNamedDataAsArrayBuffer('${scriptId}').then((value) => { + var string = utf8ArrayToString(new Uint8Array(value)); + eval(string); + }); + """.trimIndent()).asDeferred().await() + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/environment/WebViewEnvironment.kt b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/environment/WebViewEnvironment.kt new file mode 100644 index 00000000..ef26e929 --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/plugin/isolatedmodules/js/environment/WebViewEnvironment.kt @@ -0,0 +1,85 @@ +package it.airgap.vault.plugin.isolatedmodules.js.environment + +import android.content.Context +import android.content.res.AssetManager +import android.os.Build +import android.view.View +import android.webkit.WebSettings +import android.webkit.WebView +import com.getcapacitor.JSObject +import it.airgap.vault.plugin.isolatedmodules.FileExplorer +import it.airgap.vault.plugin.isolatedmodules.js.* +import it.airgap.vault.util.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +class WebViewEnvironment( + private val context: Context, + private val fileExplorer: FileExplorer, +) : JSEnvironment { + override suspend fun isSupported(): Boolean = true + + @Throws(JSException::class) + override suspend fun run(module: JSModule, action: JSModuleAction): JSObject = withContext(Dispatchers.Main) { + useIsolatedModule(module) { webView, jsAsyncResult -> + val script = """ + execute( + ${module.namespace ?: JSUndefined}, + '${module.identifier}', + ${action.toJson()}, + function (result) { + ${jsAsyncResult}.completeFromJS(JSON.stringify(result)); + }, + function (error) { + ${jsAsyncResult}.throwFromJS(error); + } + ); + """.trimIndent() + + webView.evaluateJavascript(script) + + JSObject(jsAsyncResult.await().getOrThrow()) + } + } + + override suspend fun destroy() { + /* no action */ + } + + private inline fun useIsolatedModule(module: JSModule, block: (WebView, JSAsyncResult) -> R): R { + val jsAsyncResult = JSAsyncResult() + val webView = WebView(context).apply { + visibility = View.GONE + + with(settings) { + javaScriptEnabled = true + + allowContentAccess = false + allowFileAccess = false + blockNetworkImage = true + cacheMode = WebSettings.LOAD_NO_CACHE + displayZoomControls = false + setGeolocationEnabled(false) + loadsImagesAutomatically = false + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) safeBrowsingEnabled = true + setSupportZoom(false) + } + + setLayerType(View.LAYER_TYPE_HARDWARE, null) + setNetworkAvailable(false) + + addJavascriptInterface(jsAsyncResult) + } + + with(webView) { + evaluateJavascript(fileExplorer.readIsolatedModulesScript().decodeToString()) + + val sources = fileExplorer.readModuleSources(module) + sources.forEach { evaluateJavascript(it.decodeToString()) } + } + + return block(webView, jsAsyncResult).also { + webView.destroy() + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/plugin/saplingnative/SaplingNative.kt b/android/app/src/main/java/it/airgap/vault/plugin/saplingnative/SaplingNative.kt index 918e6c8d..7f31ad0f 100644 --- a/android/app/src/main/java/it/airgap/vault/plugin/saplingnative/SaplingNative.kt +++ b/android/app/src/main/java/it/airgap/vault/plugin/saplingnative/SaplingNative.kt @@ -38,7 +38,7 @@ class SaplingNative : Plugin() { @PluginMethod fun dropProvingContext(call: PluginCall) { - with(call) { + call.executeCatching { assertReceived(Param.CONTEXT) sapling.dropProvingContext(context) resolve() @@ -47,7 +47,7 @@ class SaplingNative : Plugin() { @PluginMethod fun prepareSpendDescription(call: PluginCall) { - with(call) { + call.executeCatching { assertReceived( Param.CONTEXT, Param.SPENDING_KEY, @@ -78,7 +78,7 @@ class SaplingNative : Plugin() { @PluginMethod fun preparePartialOutputDescription(call: PluginCall) { - with(call) { + call.executeCatching { assertReceived( Param.CONTEXT, Param.ADDRESS, @@ -103,7 +103,7 @@ class SaplingNative : Plugin() { @PluginMethod fun createBindingSignature(call: PluginCall) { - with(call) { + call.executeCatching { assertReceived(Param.CONTEXT, Param.BALANCE, Param.SIGHASH) tryResolveWithDataCatchReject { diff --git a/android/app/src/main/java/it/airgap/vault/plugin/zip/Zip.kt b/android/app/src/main/java/it/airgap/vault/plugin/zip/Zip.kt new file mode 100644 index 00000000..532d9e83 --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/plugin/zip/Zip.kt @@ -0,0 +1,138 @@ +package it.airgap.vault.plugin.zip + +import android.net.Uri +import android.os.Environment +import androidx.lifecycle.lifecycleScope +import com.getcapacitor.Plugin +import com.getcapacitor.PluginCall +import com.getcapacitor.PluginMethod +import com.getcapacitor.annotation.CapacitorPlugin +import it.airgap.vault.util.Directory +import it.airgap.vault.util.assertReceived +import it.airgap.vault.util.executeCatching +import it.airgap.vault.util.getDirectory +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.io.File +import java.io.FileInputStream +import java.io.FileOutputStream +import java.io.IOException +import java.io.InputStream +import java.util.zip.ZipEntry +import java.util.zip.ZipInputStream + +@CapacitorPlugin +class Zip : Plugin() { + + @PluginMethod + fun unzip(call: PluginCall) { + call.executeCatching { + assertReceived(Param.FROM, Param.TO) + + activity.lifecycleScope.launch { + try { + unzip(from, directory, to, toDirectory) + call.resolve() + } catch (e: Exception) { + reject("Unzip failed", e) + } + } + } + } + + @Throws(IOException::class) + private suspend fun unzip(from: String, directory: Directory?, to: String, toDirectory: Directory?) { + val fromStream = getInputStream(from, directory) ?: throw IOException("Failed to create `to` InputStream") + val outFile = getFile(to, toDirectory) + + ZipInputStream(fromStream).unzip(outFile) + } + + private suspend fun ZipInputStream.unzip(destination: File) { + use { + while (true) { + val zipEntry = nextEntry ?: break + it.unzip(zipEntry, destination) + withContext(Dispatchers.IO) { + closeEntry() + } + } + } + } + + @Throws(IOException::class) + private suspend fun ZipInputStream.unzip(entry: ZipEntry, destination: File) { + val file = File(destination, entry.name).takeIf { shouldCopy(it) } ?: return + + if (entry.isDirectory) { + if (!file.isDirectory && !file.mkdirs()) throw IOException("Failed to create directory ${file.path}") + return + } + + withContext(Dispatchers.IO) { + FileOutputStream(file).use { this@unzip.copyTo(it) } + } + } + + private fun shouldCopy(file: File): Boolean { + val isIgnored = ignoredFiles.contains(file.name) + + return !isIgnored && file.parentFile?.let { shouldCopy(it) } ?: true + } + + @Throws(IOException::class) + private fun getInputStream(path: String, directory: Directory?): InputStream? = + processFilePath(path, directory, ::FileInputStream, context.contentResolver::openInputStream) + + @Throws(IOException::class) + private fun getFile(path: String, directory: Directory?): File = + processFilePath(path, directory, { it }) + + @Throws(IOException::class) + private fun processFilePath( + path: String, + directory: Directory?, + processFile: (File) -> T, + processContent: ((Uri) -> T)? = null, + ): T { + if (directory == null) { + val uri = Uri.parse(path) + if (uri.scheme == "content") { + return processContent?.invoke(uri) ?: throw IOException("`content` URI not supported") + } else if (uri.path != null) { + return processFile(File(uri.path!!)) + } + } + + val androidDirectory = context.getDirectory(directory) ?: throw IOException("Directory not found") + + return processFile(File(androidDirectory, path)) + } + + private val PluginCall.from: String + get() = getString(Param.FROM)!! + + private val PluginCall.to: String + get() = getString(Param.TO)!! + + private val PluginCall.directory: Directory? + get() = getString(Param.DIRECTORY)?.let { Directory.fromString(it) } + + private val PluginCall.toDirectory: Directory? + get() = getString(Param.TO_DIRECTORY)?.let { Directory.fromString(it) } + + private object Param { + const val FROM = "from" + const val TO = "to" + const val DIRECTORY = "directory" + const val TO_DIRECTORY = "toDirectory" + } + + private companion object { + val ignoredFiles = setOf( + "__MACOSX", + ".DS_Store" + ) + } +} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/util/Assets.kt b/android/app/src/main/java/it/airgap/vault/util/Assets.kt new file mode 100644 index 00000000..5fcbea27 --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/util/Assets.kt @@ -0,0 +1,5 @@ +package it.airgap.vault.util + +import android.content.res.AssetManager + +fun AssetManager.readBytes(path: String): ByteArray = open(path).use { stream -> stream.readBytes() } \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/util/CollectionExtensions.kt b/android/app/src/main/java/it/airgap/vault/util/CollectionExtensions.kt new file mode 100644 index 00000000..8adcdab1 --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/util/CollectionExtensions.kt @@ -0,0 +1,12 @@ +package it.airgap.vault.util + +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope + +suspend fun List.asyncMap(block: suspend (T) -> R): List = + coroutineScope { + map { + async { block(it) } + } + }.awaitAll() \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/util/Deferred.kt b/android/app/src/main/java/it/airgap/vault/util/Deferred.kt new file mode 100644 index 00000000..47ea4524 --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/util/Deferred.kt @@ -0,0 +1,29 @@ +package it.airgap.vault.util + +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock + +class ExecutableDeferred private constructor( + private val completableDeferred: CompletableDeferred, + private val init: suspend () -> T, +) : Deferred by completableDeferred { + constructor(init: suspend () -> T) : this(CompletableDeferred(), init) + + private val mutex: Mutex = Mutex() + + override suspend fun await(): T = mutex.withLock { + if (!completableDeferred.isCompleted) { + coroutineScope { + launch { + completableDeferred.complete(init()) + } + } + } + + completableDeferred.await() + } +} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/util/Filesystem.kt b/android/app/src/main/java/it/airgap/vault/util/Filesystem.kt new file mode 100644 index 00000000..4c4a9892 --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/util/Filesystem.kt @@ -0,0 +1,28 @@ +package it.airgap.vault.util + +import android.content.Context +import android.os.Environment +import java.io.File + +enum class Directory(val value: String) { + Documents("DOCUMENTS"), + Data("DATA"), + Library("LIBRARY"), + Cache("CACHE"), + External("EXTERNAL"), + ExternalStorage("EXTERNAL_STORAGE"); + + companion object { + fun fromString(value: String): Directory? = values().find { it.value == value } + } +} + +fun Context.getDirectory(directory: Directory?): File? = + when (directory) { + Directory.Documents -> Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) + Directory.Data, Directory.Library -> filesDir + Directory.Cache -> cacheDir + Directory.External -> getExternalFilesDir(null) + Directory.ExternalStorage -> Environment.getExternalStorageDirectory() + else -> null + } \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/util/Interfaces.kt b/android/app/src/main/java/it/airgap/vault/util/Interfaces.kt new file mode 100644 index 00000000..3a4a9160 --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/util/Interfaces.kt @@ -0,0 +1,5 @@ +package it.airgap.vault.util + +interface Named { + val name: String +} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/util/JS.kt b/android/app/src/main/java/it/airgap/vault/util/JS.kt index 47109dad..99135644 100644 --- a/android/app/src/main/java/it/airgap/vault/util/JS.kt +++ b/android/app/src/main/java/it/airgap/vault/util/JS.kt @@ -1,8 +1,8 @@ package it.airgap.vault.util import android.webkit.JavascriptInterface -import com.getcapacitor.JSObject import kotlinx.coroutines.CompletableDeferred +import java.lang.System.currentTimeMillis import java.util.* @Suppress("PrivatePropertyName") @@ -10,19 +10,31 @@ val JSUndefined: Any by lazy { object : Any() { override fun equals(other: Any?): Boolean = other == this || other?.equals(null) ?: true override fun hashCode(): Int = Objects.hashCode(null) - override fun toString(): String = "undefined" + override fun toString(): String = "it.airgap.vault.__UNDEFINED__" } } -class JSCompletableDeferred(val name: String) : CompletableDeferred> by CompletableDeferred() { +class JSAsyncResult(override val name: String = "$DEFAULT_NAME\$${currentTimeMillis()}") : Named { + private val completableDeferred: CompletableDeferred> = CompletableDeferred() + + suspend fun await(): Result = runCatching { + completableDeferred.await().getOrThrow() + } + @JavascriptInterface fun completeFromJS(value: String) { - complete(Result.success(JSObject(value))) + completableDeferred.complete(Result.success(value)) } @JavascriptInterface fun throwFromJS(error: String) { - complete(Result.failure(JSException(error))) + completableDeferred.complete(Result.failure(JSException(error))) + } + + override fun toString(): String = name + + companion object { + const val DEFAULT_NAME = "jsAsyncResult" } } diff --git a/android/app/src/main/java/it/airgap/vault/util/JSExtensions.kt b/android/app/src/main/java/it/airgap/vault/util/JSExtensions.kt new file mode 100644 index 00000000..5080fca9 --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/util/JSExtensions.kt @@ -0,0 +1,20 @@ +package it.airgap.vault.util + +import com.getcapacitor.JSObject + +fun JSObject.assign(other: JSObject): JSObject { + val otherNames = buildList { + val names = other.names() + for (i in 0 until (names?.length() ?: 0)) { + names?.getString(i)?.let { add(it) } + } + } + + return putAll(otherNames, other, this) +} + +private fun putAll(names: List, source: JSObject, target: JSObject): JSObject { + val name = names.firstOrNull() ?: return target + + return putAll(names.drop(1), source, target.put(name, source.get(name))) +} \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/util/PluginExtensions.kt b/android/app/src/main/java/it/airgap/vault/util/PluginExtensions.kt index 7d98067f..de43af28 100644 --- a/android/app/src/main/java/it/airgap/vault/util/PluginExtensions.kt +++ b/android/app/src/main/java/it/airgap/vault/util/PluginExtensions.kt @@ -57,11 +57,21 @@ fun PluginCall.tryResolveWithDataCatchReject(block: () -> List } } +inline fun PluginCall.executeCatching(block: PluginCall.() -> Unit) { + try { + block() + } catch (e: Throwable) { + e.printStackTrace() + reject(e.message) + } +} + +@Throws(IllegalStateException::class) fun PluginCall.assertReceived(vararg params: String, acceptEmpty: Boolean = false) { val hasAll = params.map { data.isNull(it) }.all { !it } val hasEmpty = !acceptEmpty && params.mapNotNull { getString(it)?.isBlank() }.any { it } if (!hasAll || hasEmpty) { - reject("$methodName requires: ${params.joinToString()}") + throw IllegalStateException("$methodName requires: ${params.joinToString()}") } } \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/util/StringExtensions.kt b/android/app/src/main/java/it/airgap/vault/util/StringExtensions.kt new file mode 100644 index 00000000..9cee514c --- /dev/null +++ b/android/app/src/main/java/it/airgap/vault/util/StringExtensions.kt @@ -0,0 +1,5 @@ +package it.airgap.vault.util + +fun String.startsWithAny(vararg prefixes: String, ignoreCase: Boolean = false): Boolean = prefixes.any { startsWith(it, ignoreCase) } + +fun String?.toJson(): Any = this?.let { "\"$it\"" } ?: JSUndefined \ No newline at end of file diff --git a/android/app/src/main/java/it/airgap/vault/util/WebViewExtensions.kt b/android/app/src/main/java/it/airgap/vault/util/WebViewExtensions.kt index ddbb2b67..5cb930c8 100644 --- a/android/app/src/main/java/it/airgap/vault/util/WebViewExtensions.kt +++ b/android/app/src/main/java/it/airgap/vault/util/WebViewExtensions.kt @@ -1,8 +1,17 @@ package it.airgap.vault.util +import android.annotation.SuppressLint import android.webkit.WebView +@SuppressLint("JavascriptInterface") +fun WebView.addJavascriptInterface(javascriptInterface: Named) { + addJavascriptInterface(javascriptInterface, javascriptInterface.name) +} -fun WebView.addJavascriptInterface(jsCompletableDeferred: JSCompletableDeferred) { - addJavascriptInterface(jsCompletableDeferred, jsCompletableDeferred.name) -} \ No newline at end of file +fun WebView.removeJavascriptInterface(javascriptInterface: Named) { + removeJavascriptInterface(javascriptInterface.name) +} + +fun WebView.evaluateJavascript(script: String) { + evaluateJavascript(script, null) +} diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle index 8e685785..6c7a2ab4 100644 --- a/android/capacitor.settings.gradle +++ b/android/capacitor.settings.gradle @@ -19,3 +19,6 @@ project(':capacitor-splash-screen').projectDir = new File('../node_modules/@capa include ':capacitor-status-bar' project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android') + +include ':capawesome-capacitor-file-picker' +project(':capawesome-capacitor-file-picker').projectDir = new File('../node_modules/@capawesome/capacitor-file-picker/android') diff --git a/build/android/Dockerfile b/build/android/Dockerfile index 0102f704..96e3271c 100644 --- a/build/android/Dockerfile +++ b/build/android/Dockerfile @@ -17,7 +17,7 @@ WORKDIR /app RUN yarn cache clean --force && yarn global add n && n 16.13.1 # Install app dependencies, using wildcard if package-lock exists and copy capacitor configs and ionic configs -COPY package.json yarn.lock apply-diagnostic-modules.js fix-qrscanner-gradle.js capacitor.config.ts ionic.config.json /app/ +COPY package.json yarn.lock apply-diagnostic-modules.js fix-qrscanner-gradle.js capacitor.config.ts ionic.config.json copy-builtin-modules.js /app/ # install dependencies # run ionic android build @@ -30,7 +30,7 @@ COPY . /app ARG BUILD_NR RUN sed -i -e "s/versionCode 1/versionCode $BUILD_NR/g" /app/android/app/build.gradle -# disable pure getters due to https://github.com/angular/angular-cli/issues/11439 +# disable pure getters due to https://github.com/angular/angular-cli/issues/11439 # configure mangle (keep_fnames) for bitcoinjs https://github.com/bitcoinjs/bitcoinjs-lib/issues/959 # remove unused cordova-diagnostic-plugin features # jetify dependencies diff --git a/copy-builtin-modules.js b/copy-builtin-modules.js new file mode 100644 index 00000000..29b7a3c9 --- /dev/null +++ b/copy-builtin-modules.js @@ -0,0 +1,81 @@ +const fs = require('fs') +const path = require('path') + +const browserify = require('browserify') + +const rootdir = './' +const assetsdir = path.join(rootdir, 'src/assets') +const modules = [ + { path: path.join(rootdir, 'node_modules/@airgap/aeternity') }, + { + path: path.join(rootdir, 'node_modules/@airgap/astar'), + jsenv: { + android: 'webview' + } + }, + { path: path.join(rootdir, 'node_modules/@airgap/bitcoin') }, + { path: path.join(rootdir, 'node_modules/@airgap/cosmos') }, + { + path: path.join(rootdir, 'node_modules/@airgap/ethereum'), + jsenv: { + android: 'webview' + } + }, + { path: path.join(rootdir, 'node_modules/@airgap/groestlcoin') }, + { + path: path.join(rootdir, 'node_modules/@airgap/icp'), + jsenv: { + android: 'webview' + } + }, + { + path: path.join(rootdir, 'node_modules/@airgap/moonbeam'), + jsenv: { + android: 'webview' + } + }, + { + path: path.join(rootdir, 'node_modules/@airgap/polkadot'), + jsenv: { + android: 'webview' + } + }, + { + path: path.join(rootdir, 'node_modules/@airgap/tezos'), + jsenv: { + android: 'webview' + } + } +] + +function createAssetModule(module) { + const packageJson = require(`./${path.join(module.path, 'package.json')}`) + const namespace = module.path.split('/').slice(-1)[0] + const outputDir = path.join(assetsdir, `protocol_modules/${namespace}`) + const outputFile = 'index.browserify.js' + + fs.mkdirSync(outputDir, { recursive: true }) + + browserify(`${module.path}/v1/module.js`, { standalone: namespace }) + .bundle() + .pipe(fs.createWriteStream(path.join(outputDir, outputFile))) + + + const manifest = { + name: packageJson.name, + version: packageJson.version, + author: packageJson.author, + signature: "" /* TODO */, + src: { + namespace + }, + include: [ + outputFile + ], + jsenv: module.jsenv + } + + fs.writeFileSync(path.join(outputDir, 'manifest.json'), JSON.stringify(manifest, null, 2), 'utf8') +} + +modules.forEach((path) => createAssetModule(path)) \ No newline at end of file diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index dc608319..2b8b65e9 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -36,8 +36,18 @@ A33BA9E528D9C4EF00BD8015 /* JS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33BA9E428D9C4EF00BD8015 /* JS.swift */; }; A33BA9E728D9C52D00BD8015 /* JSValue+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33BA9E628D9C52D00BD8015 /* JSValue+Additions.swift */; }; A33BA9E928D9E23E00BD8015 /* WK+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A33BA9E828D9E23E00BD8015 /* WK+Additions.swift */; }; - A3CF6E4D28CA2FA100A9A883 /* IsolatedProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3CF6E4C28CA2FA100A9A883 /* IsolatedProtocol.swift */; }; - A3CF6E4F28CA2FD900A9A883 /* IsolatedProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = A3CF6E4E28CA2FD900A9A883 /* IsolatedProtocol.m */; }; + A351B44A2979338800BE0DC9 /* Zip.swift in Sources */ = {isa = PBXBuildFile; fileRef = A351B4492979338800BE0DC9 /* Zip.swift */; }; + A351B44E297965EF00BE0DC9 /* Zip.m in Sources */ = {isa = PBXBuildFile; fileRef = A351B44D297965EF00BE0DC9 /* Zip.m */; }; + A357ED09299BD8EA00EDCA39 /* Filesystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A357ED08299BD8EA00EDCA39 /* Filesystem.swift */; }; + A3C53AA1299247640059E997 /* JSEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3C53AA0299247640059E997 /* JSEnvironment.swift */; }; + A3C53AA3299259FC0059E997 /* WebViewEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3C53AA2299259FC0059E997 /* WebViewEnvironment.swift */; }; + A3C53AA52992711E0059E997 /* Sequence+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3C53AA42992711E0059E997 /* Sequence+Additions.swift */; }; + A3CE61BC2993D827009216A2 /* FileExplorer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3CE61BB2993D827009216A2 /* FileExplorer.swift */; }; + A3CE61BE2993DF43009216A2 /* ModuleManifest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3CE61BD2993DF43009216A2 /* ModuleManifest.swift */; }; + A3CF6E4D28CA2FA100A9A883 /* IsolatedModules.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3CF6E4C28CA2FA100A9A883 /* IsolatedModules.swift */; }; + A3CF6E4F28CA2FD900A9A883 /* IsolatedModules.m in Sources */ = {isa = PBXBuildFile; fileRef = A3CF6E4E28CA2FD900A9A883 /* IsolatedModules.m */; }; + A3E4DE8F299157C2009F3C8D /* JSModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3E4DE8E299157C2009F3C8D /* JSModule.swift */; }; + A3E4DE9129915E12009F3C8D /* JSEvaluator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3E4DE9029915E12009F3C8D /* JSEvaluator.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -70,8 +80,18 @@ A33BA9E428D9C4EF00BD8015 /* JS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JS.swift; sourceTree = ""; }; A33BA9E628D9C52D00BD8015 /* JSValue+Additions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSValue+Additions.swift"; sourceTree = ""; }; A33BA9E828D9E23E00BD8015 /* WK+Additions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WK+Additions.swift"; sourceTree = ""; }; - A3CF6E4C28CA2FA100A9A883 /* IsolatedProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IsolatedProtocol.swift; sourceTree = ""; }; - A3CF6E4E28CA2FD900A9A883 /* IsolatedProtocol.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IsolatedProtocol.m; sourceTree = ""; }; + A351B4492979338800BE0DC9 /* Zip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Zip.swift; sourceTree = ""; }; + A351B44D297965EF00BE0DC9 /* Zip.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Zip.m; sourceTree = ""; }; + A357ED08299BD8EA00EDCA39 /* Filesystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filesystem.swift; sourceTree = ""; }; + A3C53AA0299247640059E997 /* JSEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSEnvironment.swift; sourceTree = ""; }; + A3C53AA2299259FC0059E997 /* WebViewEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewEnvironment.swift; sourceTree = ""; }; + A3C53AA42992711E0059E997 /* Sequence+Additions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Sequence+Additions.swift"; sourceTree = ""; }; + A3CE61BB2993D827009216A2 /* FileExplorer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileExplorer.swift; sourceTree = ""; }; + A3CE61BD2993DF43009216A2 /* ModuleManifest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModuleManifest.swift; sourceTree = ""; }; + A3CF6E4C28CA2FA100A9A883 /* IsolatedModules.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IsolatedModules.swift; sourceTree = ""; }; + A3CF6E4E28CA2FD900A9A883 /* IsolatedModules.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IsolatedModules.m; sourceTree = ""; }; + A3E4DE8E299157C2009F3C8D /* JSModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSModule.swift; sourceTree = ""; }; + A3E4DE9029915E12009F3C8D /* JSEvaluator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSEvaluator.swift; sourceTree = ""; }; AF277DCFFFF123FFC6DF26C7 /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; }; AF51FD2D460BCFE21FA515B2 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = ""; }; FC68EB0AF532CFC21C3344DD /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = ""; }; @@ -120,6 +140,7 @@ 504EC3061FED79650016851F /* App */ = { isa = PBXGroup; children = ( + A351B4482979337600BE0DC9 /* Zip */, A36CA3BE28CA2AAE00635173 /* IsolatedModules */, 8885568F2721A9EC009A831D /* public */, 885F55E525EE220A00D85A88 /* SaplingNative */, @@ -177,6 +198,7 @@ children = ( 88AE2EEB23D5CB1C00428560 /* Extensions */, A33BA9E428D9C4EF00BD8015 /* JS.swift */, + A357ED08299BD8EA00EDCA39 /* Filesystem.swift */, ); path = Helpers; sourceTree = ""; @@ -187,6 +209,7 @@ 88AE2EEC23D5CB3200428560 /* PluginCall+Additions.swift */, A33BA9E628D9C52D00BD8015 /* JSValue+Additions.swift */, A33BA9E828D9E23E00BD8015 /* WK+Additions.swift */, + A3C53AA42992711E0059E997 /* Sequence+Additions.swift */, ); path = Extensions; sourceTree = ""; @@ -210,15 +233,46 @@ path = Camera; sourceTree = ""; }; + A351B4482979337600BE0DC9 /* Zip */ = { + isa = PBXGroup; + children = ( + A351B4492979338800BE0DC9 /* Zip.swift */, + A351B44D297965EF00BE0DC9 /* Zip.m */, + ); + path = Zip; + sourceTree = ""; + }; A36CA3BE28CA2AAE00635173 /* IsolatedModules */ = { isa = PBXGroup; children = ( - A3CF6E4C28CA2FA100A9A883 /* IsolatedProtocol.swift */, - A3CF6E4E28CA2FD900A9A883 /* IsolatedProtocol.m */, + A3E4DE8D299157B1009F3C8D /* JS */, + A3CF6E4C28CA2FA100A9A883 /* IsolatedModules.swift */, + A3CF6E4E28CA2FD900A9A883 /* IsolatedModules.m */, + A3CE61BB2993D827009216A2 /* FileExplorer.swift */, + A3CE61BD2993DF43009216A2 /* ModuleManifest.swift */, ); path = IsolatedModules; sourceTree = ""; }; + A3E4DE8D299157B1009F3C8D /* JS */ = { + isa = PBXGroup; + children = ( + A3E4DE9229915E20009F3C8D /* Environment */, + A3E4DE9029915E12009F3C8D /* JSEvaluator.swift */, + A3E4DE8E299157C2009F3C8D /* JSModule.swift */, + ); + path = JS; + sourceTree = ""; + }; + A3E4DE9229915E20009F3C8D /* Environment */ = { + isa = PBXGroup; + children = ( + A3C53AA0299247640059E997 /* JSEnvironment.swift */, + A3C53AA2299259FC0059E997 /* WebViewEnvironment.swift */, + ); + path = Environment; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -340,26 +394,36 @@ buildActionMask = 2147483647; files = ( 88AE2EF323D5DC3900428560 /* Keychain.swift in Sources */, + A3C53AA3299259FC0059E997 /* WebViewEnvironment.swift in Sources */, A33BA9E928D9E23E00BD8015 /* WK+Additions.swift in Sources */, 88F9F14723D059AE008351D0 /* AppInfo.m in Sources */, - A3CF6E4F28CA2FD900A9A883 /* IsolatedProtocol.m in Sources */, + A351B44E297965EF00BE0DC9 /* Zip.m in Sources */, + A3CF6E4F28CA2FD900A9A883 /* IsolatedModules.m in Sources */, A33BA9E728D9C52D00BD8015 /* JSValue+Additions.swift in Sources */, - A3CF6E4D28CA2FA100A9A883 /* IsolatedProtocol.swift in Sources */, + A3CF6E4D28CA2FA100A9A883 /* IsolatedModules.swift in Sources */, + A3E4DE8F299157C2009F3C8D /* JSModule.swift in Sources */, 885F55E825EE224200D85A88 /* SaplingNative.m in Sources */, 49690A7E25C2BF80004A3586 /* VaultError.swift in Sources */, + A3C53AA1299247640059E997 /* JSEnvironment.swift in Sources */, 88AE2EF923D5DC8300428560 /* SecureStorage.swift in Sources */, 88F9F15623D06A76008351D0 /* CameraPreview.m in Sources */, A33BA9E528D9C4EF00BD8015 /* JS.swift in Sources */, 88AE2EF523D5DC5100428560 /* LocalAuthentication.swift in Sources */, + A357ED09299BD8EA00EDCA39 /* Filesystem.swift in Sources */, + A3CE61BE2993DF43009216A2 /* ModuleManifest.swift in Sources */, 504EC3081FED79650016851F /* AppDelegate.swift in Sources */, + A3C53AA52992711E0059E997 /* Sequence+Additions.swift in Sources */, 88AE2EEF23D5D7B300428560 /* SecurityUtils.m in Sources */, 88F9F15423D06A00008351D0 /* CameraPreview.swift in Sources */, + A351B44A2979338800BE0DC9 /* Zip.swift in Sources */, 88AE2EF123D5DC2400428560 /* DeviceIntegrity.swift in Sources */, 885F55EB25EE226300D85A88 /* SaplingNative.swift in Sources */, + A3E4DE9129915E12009F3C8D /* JSEvaluator.swift in Sources */, 88AE2EED23D5CB3200428560 /* PluginCall+Additions.swift in Sources */, 88F9F14423D058DD008351D0 /* AppInfo.swift in Sources */, 88AE2EE823D5C7A500428560 /* SecurityUtils.swift in Sources */, 88F9F15223D069E9008351D0 /* CameraController.swift in Sources */, + A3CE61BC2993D827009216A2 /* FileExplorer.swift in Sources */, 88AE2EF723D5DC7400428560 /* SecureScreen.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ios/App/App/Helpers/Extensions/JSValue+Additions.swift b/ios/App/App/Helpers/Extensions/JSValue+Additions.swift index 12f0fec1..1c573576 100644 --- a/ios/App/App/Helpers/Extensions/JSValue+Additions.swift +++ b/ios/App/App/Helpers/Extensions/JSValue+Additions.swift @@ -8,6 +8,13 @@ import Foundation import Capacitor +extension String: JSONConvertible { + + func toJSONString() throws -> String { + return "\"\(self)\"" + } +} + extension JSObject: JSONConvertible { func toJSONString() throws -> String { @@ -23,15 +30,15 @@ extension JSObject: JSONConvertible { extension JSArray: JSONConvertible { func toJSONString() throws -> String { - let jsonEncoder = JSONEncoder() - let elements = try map { (value: JSValue) throws -> String in + let elements = try map { value -> String in if JSONSerialization.isValidJSONObject(value) { let data = try JSONSerialization.data(withJSONObject: value, options: []) return String(data: data, encoding: .utf8)! - } /*else if let encodable = value as? Encodable { + } else if let encodable = value as? Encodable { + let jsonEncoder = JSONEncoder() let data = try jsonEncoder.encode(encodable) return String(data: data, encoding: .utf8)! - } */else if let jsonConvertible = value as? JSONConvertible { + } else if let jsonConvertible = value as? JSONConvertible { return try jsonConvertible.toJSONString() } else { throw JSError.invalidJSON @@ -41,3 +48,17 @@ extension JSArray: JSONConvertible { return "[\(elements.joined(separator: ","))]" } } + +extension NSNumber: JSONConvertible { + + func toJSONString() throws -> String { + stringValue + } +} + +extension NSNull: JSONConvertible { + + func toJSONString() throws -> String { + "null" + } +} diff --git a/ios/App/App/Helpers/Extensions/Sequence+Additions.swift b/ios/App/App/Helpers/Extensions/Sequence+Additions.swift new file mode 100644 index 00000000..fe1f30c7 --- /dev/null +++ b/ios/App/App/Helpers/Extensions/Sequence+Additions.swift @@ -0,0 +1,23 @@ +// +// Sequence+Additions.swift +// App +// +// Created by Julia Samol on 07.02.23. +// + +import Foundation + +extension Sequence { + func asyncMap(_ transform: @escaping (Element) async throws -> T) async throws -> [T] { + let tasks = map { element in + Task { try await transform(element) } + } + + var newElements = [T]() + for task in tasks { + newElements.append(try await task.value) + } + + return newElements + } +} diff --git a/ios/App/App/Helpers/Extensions/WK+Additions.swift b/ios/App/App/Helpers/Extensions/WK+Additions.swift index 28f141e7..8f95a782 100644 --- a/ios/App/App/Helpers/Extensions/WK+Additions.swift +++ b/ios/App/App/Helpers/Extensions/WK+Additions.swift @@ -10,7 +10,28 @@ import WebKit extension WKUserContentController { - func add(_ jsCallbackHandler: JSCallbackHandler) { - add(jsCallbackHandler, name: jsCallbackHandler.name) + func add(_ scriptMessageHandler: T) where T.ID == String { + add(scriptMessageHandler, name: scriptMessageHandler.id) + } + + func remove(_ scriptMessageHandler: T) where T.ID == String { + removeScriptMessageHandler(forName: scriptMessageHandler.id) + } +} + +extension WKWebView { + + @MainActor + @discardableResult + func evaluateJavaScriptAsync(_ javaScriptString: String) async throws -> Any? { + return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in + self.evaluateJavaScript(javaScriptString) { data, error in + if let error = error { + continuation.resume(throwing: error) + } else { + continuation.resume(returning: data) + } + } + } } } diff --git a/ios/App/App/Helpers/Filesystem.swift b/ios/App/App/Helpers/Filesystem.swift new file mode 100644 index 00000000..41729a28 --- /dev/null +++ b/ios/App/App/Helpers/Filesystem.swift @@ -0,0 +1,32 @@ +// +// Filesystem.swift +// App +// +// Created by Julia Samol on 14.02.23. +// + +import Foundation + +enum Directory: String { + case documents = "DOCUMENTS" + case data = "DATA" + case library = "LIBRARY" + case cache = "CACHE" + case external = "EXTERNAL" + case externalStorage = "EXTERNAL_STORAGE" +} + +extension FileManager { + func getDirectory(from directory: Directory?) -> FileManager.SearchPathDirectory? { + switch directory { + case .library: + return .libraryDirectory + case .cache: + return .cachesDirectory + case .documents, .data, .external, .externalStorage: + return .documentDirectory + default: + return nil + } + } +} diff --git a/ios/App/App/Helpers/JS.swift b/ios/App/App/Helpers/JS.swift index bfc7d554..71d37b05 100644 --- a/ios/App/App/Helpers/JS.swift +++ b/ios/App/App/Helpers/JS.swift @@ -22,21 +22,25 @@ protocol JSONConvertible { func toJSONString() throws -> String } -class JSCallbackHandler: NSObject, WKScriptMessageHandler { - private typealias Listener = (Result<[String: Any], Error>) -> () +class JSAsyncResult: NSObject, Identifiable, WKScriptMessageHandler { + private typealias Listener = (Result) -> () - let name: String + private static let defaultName: String = "jsAsyncResult" + private static let fieldResult: String = "result" + private static let fieldError: String = "error" + + public let id: String private var resultManager: ResultManager private let listenerRegistry: ListenerRegistry - init(name: String) { - self.name = name + init(id: String = "\(JSAsyncResult.defaultName)\(Int(Date().timeIntervalSince1970))") { + self.id = id self.resultManager = .init() self.listenerRegistry = .init() } - func awaitResult() async throws -> [String: Any] { + func awaitResult() async throws -> Any { if let result = await resultManager.result { return try result.get() } @@ -55,20 +59,15 @@ class JSCallbackHandler: NSObject, WKScriptMessageHandler { } func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { - guard message.name == name, let body = message.body as? [String: String] else { return } - + guard message.name == id, let body = message.body as? [String: Any] else { return } + Task { do { - let result = body["result"] - let error = body["error"] - + let result = body[Self.fieldResult] + let error = body[Self.fieldError] + if let result = result, error == nil { - let deserialized = try JSONSerialization.jsonObject(with: .init(result.utf8)) - if let dictionary = deserialized as? [String: Any] { - await listenerRegistry.notifyAll(with: .success(dictionary)) - } else { - await listenerRegistry.notifyAll(with: .success(["result": deserialized])) - } + await listenerRegistry.notifyAll(with: .success(result)) } else if let error = error { throw JSError.fromScript(error) } else { @@ -81,9 +80,9 @@ class JSCallbackHandler: NSObject, WKScriptMessageHandler { } private actor ResultManager { - private(set) var result: Result<[String: Any], Error>? + private(set) var result: Result? - func setResult(_ result: Result<[String: Any], Error>) { + func setResult(_ result: Result) { self.result = result } } @@ -95,14 +94,13 @@ class JSCallbackHandler: NSObject, WKScriptMessageHandler { listeners.append(listener) } - func notifyAll(with result: Result<[String: Any], Error>) { + func notifyAll(with result: Result) { listeners.forEach { $0(result) } listeners.removeAll() } } } - enum JSError: Swift.Error { case invalidJSON - case fromScript(String) + case fromScript(Any) } diff --git a/ios/App/App/IsolatedModules/FileExplorer.swift b/ios/App/App/IsolatedModules/FileExplorer.swift new file mode 100644 index 00000000..96fa4ed9 --- /dev/null +++ b/ios/App/App/IsolatedModules/FileExplorer.swift @@ -0,0 +1,227 @@ +// +// FileExplorer.swift +// App +// +// Created by Julia Samol on 08.02.23. +// + +import Foundation + +// MARK: FileExplorer + +struct FileExplorer { + static let shared: FileExplorer = .init() + + private let assetsExplorer: AssetsExplorer + private let documentExplorer: DocumentExplorer + + private let fileManager: FileManager + + init(fileManager: FileManager = .default) { + self.assetsExplorer = .init(fileManager: fileManager) + self.documentExplorer = .init(fileManager: fileManager) + self.fileManager = fileManager + } + + func readIsolatedModulesScript() throws -> Data { + try assetsExplorer.readIsolatedModulesScript() + } + + func loadAssetModules() throws -> [JSModule] { + try loadModules(using: assetsExplorer, creatingModuleWith: JSModule.Asset.init).map { .asset($0) } + } + + func loadInstalledModule(_ identifier: String) throws -> JSModule { + let manifest = try documentExplorer.readModuleManifest(identifier) + + return .installed(try loadModule(identifier, fromManifest: manifest, creatingModuleWith: JSModule.Instsalled.init)) + } + + func loadInstalledModules() throws -> [JSModule] { + try loadModules(using: documentExplorer, creatingModuleWith: JSModule.Instsalled.init).map { .installed($0) } + } + + func loadPreviewModule(atPath path: String, locatedIn directory: Directory) throws -> JSModule { + guard let directory = fileManager.getDirectory(from: directory), + let url = fileManager.urls(for: directory, in: .userDomainMask).first?.appendingPathComponent(path) else { + throw Error.invalidDirectory + } + + let identifier = url.pathComponents.last ?? "module" + let manifest = try fileManager.contents(at: url.appendingPathComponent(FileExplorer.manifestFilename)) + + return .preview(try loadModule(identifier, fromManifest: manifest) { identifier, namespace, preferredEnvironment, sources in + JSModule.Preview(identifier: identifier, namespace: namespace, preferredEnvironment: preferredEnvironment, sources: sources, path: url) + }) + } + + func readModuleSources(_ module: JSModule) throws -> [Data] { + switch module { + case .asset(let asset): + return try assetsExplorer.readModuleSources(asset) + case .installed(let installed): + return try documentExplorer.readModuleSources(installed) + case .preview(let preview): + return try preview.sources.lazy.map { try fileManager.contents(at: preview.path.appendingPathComponent($0)) } + } + } + + func readModuleManifest(_ module: JSModule) throws -> Data { + switch module { + case .asset(let asset): + return try assetsExplorer.readModuleManifest(asset.identifier) + case .installed(let installed): + return try documentExplorer.readModuleManifest(installed.identifier) + case .preview(let preview): + return try fileManager.contents(at: preview.path.appendingPathComponent(FileExplorer.manifestFilename)) + } + } + + private func loadModules( + using explorer: E, + creatingModuleWith moduleInit: (_ identifier: String, _ namespace: String?, _ preferredEnvironment: JSEnvironmentKind, _ sources: [String]) -> T + ) throws -> [T] where E.T == T { + try explorer.listModules().map { module in + try loadModule(module, fromManifest: try explorer.readModuleManifest(module), creatingModuleWith: moduleInit) + } + } + + private func loadModule( + _ identifier: String, + fromManifest manifestData: Data, + creatingModuleWith moduleInit: (_ identifier: String, _ namespace: String?, _ preferredEnvironment: JSEnvironmentKind, _ sources: [String]) -> T + ) throws -> T { + let jsonDecoder = JSONDecoder() + + let manifest = try jsonDecoder.decode(ModuleManifest.self, from: manifestData) + let namespace = manifest.src?.namespace + let preferredEnvironment = manifest.jsenv?.ios ?? .webview + let sources: [String] = manifest.include.compactMap { source in + guard source.hasSuffix(".js") else { return nil } + return source + } + + return moduleInit(identifier, namespace, preferredEnvironment, sources) + } +} + +// MARK: AssetsExplorer + +private struct AssetsExplorer: DynamicSourcesExplorer { + typealias T = JSModule.Asset + + static let assetsURL: URL = Bundle.main.url(forResource: "public", withExtension: nil)!.appendingPathComponent("assets") + private static let script: String = "native/isolated_modules/isolated-modules.script.js" + private static let modulesDir: String = "protocol_modules" + + private let fileManager: FileManager + + init(fileManager: FileManager) { + self.fileManager = fileManager + } + + func readIsolatedModulesScript() throws -> Data { + try readData(atPath: Self.script) + } + + func listModules() throws -> [String] { + let url = Self.assetsURL.appendingPathComponent(Self.modulesDir) + return try fileManager.contentsOfDirectory(atPath: url.path) + } + + func modulePath(_ module: String, forPath path: String) throws -> String { + "\(Self.modulesDir)/\(module)/\(path)" + } + + func readModuleSources(_ module: JSModule.Asset) throws -> [Data] { + try module.sources.lazy.map { try readData(atPath: modulePath(module.identifier, forPath: $0)) } + } + + func readModuleManifest(_ module: String) throws -> Data { + try readData(atPath: modulePath(module, forPath: FileExplorer.manifestFilename)) + } + + private func readData(atPath pathComponent: String) throws -> Data { + let url = Self.assetsURL.appendingPathComponent(pathComponent) + return try fileManager.contents(at: url) + } +} + +// MARK: DocumentExplorer + +private struct DocumentExplorer: DynamicSourcesExplorer { + typealias T = JSModule.Instsalled + + private static let modulesDir: String = "protocol_modules" + + private let fileManager: FileManager + + init(fileManager: FileManager) { + self.fileManager = fileManager + } + + func listModules() throws -> [String] { + guard let url = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { + return [] + } + + let modulesDirPath = url.appendingPathComponent(Self.modulesDir).path + guard fileManager.fileExists(atPath: modulesDirPath) else { + return [] + } + + return try fileManager.contentsOfDirectory(atPath: modulesDirPath) + } + + func modulePath(_ module: String, ofPath path: String) throws -> String { + return "\(Self.modulesDir)/\(module)/\(path)" + } + + func readModuleSources(_ module: JSModule.Instsalled) throws -> [Data] { + try module.sources.lazy.map { try readData(atPath: modulePath(module.identifier, ofPath: $0)) } + } + + func readModuleManifest(_ module: String) throws -> Data { + try readData(atPath: modulePath(module, ofPath: FileExplorer.manifestFilename)) + } + + private func readData(atPath path: String) throws -> Data { + guard let url = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent(path) else { + throw Error.invalidDirectory + } + + return try fileManager.contents(at: url) + } +} + +// MARK: DynamicSourcesExplorer + +private protocol DynamicSourcesExplorer { + associatedtype T + + func listModules() throws -> [String] + + func readModuleSources(_ module: T) throws -> [Data] + func readModuleManifest(_ module: String) throws -> Data +} + +// MARK: Extensions + +private extension FileExplorer { + static let manifestFilename: String = "manifest.json" +} + +private extension FileManager { + func contents(at url: URL) throws -> Data { + guard let data = contents(atPath: url.path) else { + throw Error.invalidPath + } + + return data + } +} + +private enum Error: Swift.Error { + case invalidPath + case invalidDirectory +} diff --git a/ios/App/App/IsolatedModules/IsolatedModules.m b/ios/App/App/IsolatedModules/IsolatedModules.m new file mode 100644 index 00000000..de5aa560 --- /dev/null +++ b/ios/App/App/IsolatedModules/IsolatedModules.m @@ -0,0 +1,17 @@ +// +// IsolatedProtocol.m +// App +// +// Created by Julia Samol on 08.09.22. +// + +#import +#import + +// disable true isolation until it's production ready +//CAP_PLUGIN(IsolatedModules, "IsolatedModules", +// CAP_PLUGIN_METHOD(previewModule, CAPPluginReturnPromise); +// CAP_PLUGIN_METHOD(registerModule, CAPPluginReturnPromise); +// CAP_PLUGIN_METHOD(loadModules, CAPPluginReturnPromise); +// CAP_PLUGIN_METHOD(callMethod, CAPPluginReturnPromise); +//) diff --git a/ios/App/App/IsolatedModules/IsolatedModules.swift b/ios/App/App/IsolatedModules/IsolatedModules.swift new file mode 100644 index 00000000..f2212cc1 --- /dev/null +++ b/ios/App/App/IsolatedModules/IsolatedModules.swift @@ -0,0 +1,206 @@ +// +// IsolatedModules.swift +// App +// +// Created by Julia Samol on 08.09.22. +// + +import Foundation +import Capacitor +import WebKit + +@objc(IsolatedModules) +public class IsolatedModules: CAPPlugin { + private let fileExplorer: FileExplorer = .shared + private lazy var jsEvaluator: JSEvaluator = .init(fileExplorer: fileExplorer) + + @objc func previewModule(_ call: CAPPluginCall) { + call.assertReceived(forMethod: "previewModule", requiredParams: Param.PATH, Param.DIRECTORY) + + do { + guard let path = call.path, let directory = call.directory else { + throw Error.invalidData + } + + Task { + do { + let module = try fileExplorer.loadPreviewModule(atPath: path, locatedIn: directory) + let manifest = try fileExplorer.readModuleManifest(module) + let moduleJSON = try await jsEvaluator.evaluatePreviewModule(module) + + call.resolve([ + "module": moduleJSON, + "manifest": try JSONSerialization.jsonObject(with: manifest) + ]) + } catch { + call.reject("Error: \(error)") + } + } + } catch { + call.reject("Error: \(error)") + } + } + + @objc func registerModule(_ call: CAPPluginCall) { + call.assertReceived(forMethod: "registerModule", requiredParams: Param.IDENTIFIER, Param.PROTOCOL_IDENTIFIERS) + + do { + guard let identifier = call.identifier, let protocolIdentifiers = call.protocolIdentifiers else { + throw Error.invalidData + } + + Task { + do { + let module = try fileExplorer.loadInstalledModule(identifier) + await jsEvaluator.registerModule(module, forProtocols: protocolIdentifiers) + + call.resolve() + } catch { + call.reject("Error: \(error)") + } + } + } catch { + call.reject("Error: \(error)") + } + } + + @objc func loadModules(_ call: CAPPluginCall) { + Task { + do { + let protocolType = call.protocolType + let modules: [JSModule] = try fileExplorer.loadAssetModules() + (try fileExplorer.loadInstalledModules()) + + call.resolve(try await jsEvaluator.evaluateLoadModules(modules, for: protocolType)) + } catch { + call.reject("Error: \(error)") + } + } + } + + @objc func callMethod(_ call: CAPPluginCall) { + call.assertReceived(forMethod: "callMethod", requiredParams: Param.TARGET, Param.METHOD) + + do { + guard let target = call.target, let method = call.method else { + throw Error.invalidData + } + + Task { + do { + switch target { + case .offlineProtocol: + call.assertReceived(forMethod: "callMethod", requiredParams: Param.PROTOCOL_IDENTIFIER) + + guard let protocolIdentifier = call.protocolIdentifier else { + throw Error.invalidData + } + + let args = call.args + + call.resolve( + try await jsEvaluator.evaluateCallOfflineProtocolMethod(method, ofProtocol: protocolIdentifier, withArgs: args) + ) + case .onlineProtocol: + call.assertReceived(forMethod: "callMethod", requiredParams: Param.PROTOCOL_IDENTIFIER) + + guard let protocolIdentifier = call.protocolIdentifier else { + throw Error.invalidData + } + + let args = call.args + let networkID = call.networkID + + call.resolve( + try await jsEvaluator.evaluateCallOnlineProtocolMethod(method, ofProtocol: protocolIdentifier, onNetwork: networkID, withArgs: args) + ) + case .blockExplorer: + call.assertReceived(forMethod: "callMethod", requiredParams: Param.PROTOCOL_IDENTIFIER) + + guard let protocolIdentifier = call.protocolIdentifier else { + throw Error.invalidData + } + + let args = call.args + let networkID = call.networkID + + call.resolve( + try await jsEvaluator.evaluateCallBlockExplorerMethod(method, ofProtocol: protocolIdentifier, onNetwork: networkID, withArgs: args) + ) + case .v3SerializerCompanion: + call.assertReceived(forMethod: "callMethod", requiredParams: Param.MODULE_IDENTIFIER) + + guard let moduleIdentifier = call.moduleIdentifier else { + throw Error.invalidData + } + + let args = call.args + + call.resolve( + try await jsEvaluator.evaluateCallV3SerializerCompanionMethod(method, ofModule: moduleIdentifier, withArgs: args) + ) + } + } catch { + call.reject("Error: \(error)") + } + } + } catch { + call.reject("Error: \(error)") + } + } + + struct Param { + static let PATH = "path" + static let DIRECTORY = "directory" + static let IDENTIFIER = "identifier" + static let PROTOCOL_IDENTIFIERS = "protocolIdentifiers" + static let PROTOCOL_TYPE = "protocolType" + static let TARGET = "target" + static let METHOD = "method" + static let ARGS = "args" + static let PROTOCOL_IDENTIFIER = "protocolIdentifier" + static let MODULE_IDENTIFIER = "moduleIdentifier" + static let NETWORK_ID = "networkId" + } + + enum Error: Swift.Error { + case invalidData + } +} + +private extension CAPPluginCall { + var path: String? { return getString(IsolatedModules.Param.PATH) } + + var directory: Directory? { + guard let directory = getString(IsolatedModules.Param.DIRECTORY) else { return nil } + return .init(rawValue: directory) + } + + var identifier: String? { return getString(IsolatedModules.Param.IDENTIFIER) } + var protocolIdentifiers: [String]? { + return getArray(IsolatedModules.Param.PROTOCOL_IDENTIFIERS)?.compactMap { + if let string = $0 as? String { + return string + } else { + return nil + } + } + } + + var protocolType: JSProtocolType? { + guard let protocolType = getString(IsolatedModules.Param.PROTOCOL_TYPE) else { return nil } + return .init(rawValue: protocolType) + } + + var target: JSCallMethodTarget? { + guard let target = getString(IsolatedModules.Param.TARGET) else { return nil } + return .init(rawValue: target) + } + + var method: String? { return getString(IsolatedModules.Param.METHOD) } + var args: JSArray? { return getArray(IsolatedModules.Param.ARGS)} + + var protocolIdentifier: String? { return getString(IsolatedModules.Param.PROTOCOL_IDENTIFIER) } + var moduleIdentifier: String? { return getString(IsolatedModules.Param.MODULE_IDENTIFIER) } + + var networkID: String? { return getString(IsolatedModules.Param.NETWORK_ID) } +} diff --git a/ios/App/App/IsolatedModules/IsolatedProtocol.m b/ios/App/App/IsolatedModules/IsolatedProtocol.m deleted file mode 100644 index 69f40b93..00000000 --- a/ios/App/App/IsolatedModules/IsolatedProtocol.m +++ /dev/null @@ -1,14 +0,0 @@ -// -// IsolatedProtocol.m -// App -// -// Created by Julia Samol on 08.09.22. -// - -#import -#import - -CAP_PLUGIN(IsolatedProtocol, "IsolatedProtocol", - CAP_PLUGIN_METHOD(getField, CAPPluginReturnPromise); - CAP_PLUGIN_METHOD(callMethod, CAPPluginReturnPromise); -) diff --git a/ios/App/App/IsolatedModules/IsolatedProtocol.swift b/ios/App/App/IsolatedModules/IsolatedProtocol.swift deleted file mode 100644 index c02dd96e..00000000 --- a/ios/App/App/IsolatedModules/IsolatedProtocol.swift +++ /dev/null @@ -1,201 +0,0 @@ -// -// IsolatedProtocol.swift -// App -// -// Created by Julia Samol on 08.09.22. -// - -import Foundation -import Capacitor -import WebKit - -@objc(IsolatedProtocol) -public class IsolatedProtocol: CAPPlugin, WKNavigationDelegate { - private static let assetsURL: URL? = Bundle.main.url(forResource: "public", withExtension: nil)?.appendingPathComponent("assets") - - private static let coinlibSource: String = "libs/airgap-coin-lib.browserify.js" - private static let commonSource: String = "native/isolated_modules/protocol_common.js" - - @objc func getField(_ call: CAPPluginCall) { - call.assertReceived(forMethod: "getField", requiredParams: Param.IDENTIFIER, Param.KEY) - - do { - guard let identifier = call.identifier, let key = call.key else { - throw Error.invalidData - } - - let options = call.options - - Task { - do { - let result = try await getField( - key, - ofProtocol: identifier, - builtWithOptions: options - ) - call.resolve(result) - } catch { - call.reject("Error: \(error)") - } - } - } catch { - call.reject("Error: \(error)") - } - } - - @objc func callMethod(_ call: CAPPluginCall) { - call.assertReceived(forMethod: "callMethod", requiredParams: Param.IDENTIFIER, Param.KEY) - - do { - guard let identifier = call.identifier, let key = call.key else { - throw Error.invalidData - } - - let options = call.options - let args = call.args - - Task { - do { - let result = try await callMethod( - key, - ofProtocol: identifier, - builtWithOptions: options, - withArgs: args?.replaceNullWithUndefined() - ) - call.resolve(result) - } catch { - call.reject("Error: \(error)") - } - } - } catch { - call.reject("Error: \(error)") - } - } - - private func getField(_ key: String, ofProtocol identifier: String, builtWithOptions options: JSObject?) async throws -> [String: Any] { - try await spawnCoinlibWebView( - forProtocol: identifier, - usingOptions: options, - for: .getField, - injectScript: """ - var __platform__field = '\(key)' - """ - ) - } - - private func callMethod( - _ key: String, - ofProtocol identifier: String, - builtWithOptions options: JSObject?, - withArgs args: JSArray? - ) async throws -> [String: Any] { - let args: String = try { - if let args = args { - return try args.toJSONString() - } else { - return "[]" - } - }() - - return try await spawnCoinlibWebView( - forProtocol: identifier, - usingOptions: options, - for: .callMethod, - injectScript: """ - var __platform__method = '\(key)' - var __platform__args = \(args) - """ - ) - } - - @MainActor - private func spawnCoinlibWebView( - forProtocol identifier: String, - usingOptions options: JSObject?, - for action: JSProtocolAction, - injectScript script: String? = nil - ) async throws -> [String: Any] { - guard let assetsURL = Self.assetsURL else { - throw Error.fileNotFound - } - - let callbackHandler = JSCallbackHandler(name: "resultCallbackHandler") - - let html = """ - - - - """ - - let userContentController = WKUserContentController() - userContentController.add(callbackHandler) - - let webViewConfiguration = WKWebViewConfiguration() - webViewConfiguration.userContentController = userContentController - - let webView = WKWebView(frame: .zero, configuration: webViewConfiguration) - webView.navigationDelegate = self - let _ = webView.load( - .init(html.utf8), - mimeType: "text/html", - characterEncodingName: "utf-8", - baseURL: assetsURL - ) - - return try await callbackHandler.awaitResult() - } - - enum JSProtocolAction: String { - case getField - case callMethod - } - - struct Param { - static let IDENTIFIER = "identifier" - static let OPTIONS = "options" - static let KEY = "key" - static let ARGS = "args" - } - - enum Error: Swift.Error { - case fileNotFound - case invalidData - } -} - -private extension CAPPluginCall { - var identifier: String? { return getString(IsolatedProtocol.Param.IDENTIFIER) } - var options: JSObject? { return getObject(IsolatedProtocol.Param.OPTIONS) } - var key: String? { return getString(IsolatedProtocol.Param.KEY) } - var args: JSArray? { return getArray(IsolatedProtocol.Param.ARGS)} -} - -private extension JSArray { - func replaceNullWithUndefined() -> JSArray { - map { - if $0 is NSNull { - return JSUndefined.value - } else { - return $0 - } - } - } -} diff --git a/ios/App/App/IsolatedModules/JS/Environment/JSEnvironment.swift b/ios/App/App/IsolatedModules/JS/Environment/JSEnvironment.swift new file mode 100644 index 00000000..605d12f3 --- /dev/null +++ b/ios/App/App/IsolatedModules/JS/Environment/JSEnvironment.swift @@ -0,0 +1,17 @@ +// +// JSEnvironment.swift +// App +// +// Created by Julia Samol on 07.02.23. +// + +import Foundation + +protocol JSEnvironment { + func run(_ action: JSModuleAction, in module: JSModule) async throws -> [String: Any] + func destroy() async throws +} + +enum JSEnvironmentKind: String, Codable { + case webview +} diff --git a/ios/App/App/IsolatedModules/JS/Environment/WebViewEnvironment.swift b/ios/App/App/IsolatedModules/JS/Environment/WebViewEnvironment.swift new file mode 100644 index 00000000..19d1e12a --- /dev/null +++ b/ios/App/App/IsolatedModules/JS/Environment/WebViewEnvironment.swift @@ -0,0 +1,90 @@ +// +// WebViewEnvironment.swift +// App +// +// Created by Julia Samol on 07.02.23. +// + +import Foundation +import WebKit + +class WebViewEnvironment: NSObject, JSEnvironment, WKNavigationDelegate { + private let fileExplorer: FileExplorer + + init(fileExplorer: FileExplorer) { + self.fileExplorer = fileExplorer + } + + @MainActor + func run(_ action: JSModuleAction, in module: JSModule) async throws -> [String: Any] { + let jsAsyncResult = JSAsyncResult() + + let userContentController = WKUserContentController() + userContentController.add(jsAsyncResult) + + let webViewConfiguration = WKWebViewConfiguration() + webViewConfiguration.userContentController = userContentController + + let webView = WKWebView(frame: .zero, configuration: webViewConfiguration) + webView.navigationDelegate = self + + do { + defer { + userContentController.remove(jsAsyncResult) + webView.stopLoading() + webView.scrollView.delegate = nil + webView.navigationDelegate = nil + webView.removeFromSuperview() + } + + guard let scriptSource = String(data: try fileExplorer.readIsolatedModulesScript(), encoding: .utf8) else { + throw Error.invalidSource + } + try await webView.evaluateJavaScriptAsync(scriptSource) + + for source in try fileExplorer.readModuleSources(module) { + guard let string = String(data: source, encoding: .utf8) else { + throw Error.invalidSource + } + + try await webView.evaluateJavaScriptAsync(string) + } + + let script = """ + function postMessage(message) { + window.webkit.messageHandlers.\(jsAsyncResult.id).postMessage(message); + }; + + execute( + \(try module.namespace ?? (try JSUndefined.value.toJSONString())), + '\(module.identifier)', + \(try action.toJSONString()), + function (result) { + postMessage({ result: JSON.parse(JSON.stringify(result)) }); + }, + function (error) { + postMessage({ error }) + } + ); + """ + + webView.evaluateJavaScript(script, completionHandler: nil) + guard let result = try await jsAsyncResult.awaitResult() as? [String: Any] else { + throw Error.invalidResult + } + + return result + } catch { + throw error + } + } + + func destroy() async throws { + /* no action */ + } + + private enum Error: Swift.Error { + case invalidSource + case invalidResult + } +} diff --git a/ios/App/App/IsolatedModules/JS/JSEvaluator.swift b/ios/App/App/IsolatedModules/JS/JSEvaluator.swift new file mode 100644 index 00000000..2ca510f5 --- /dev/null +++ b/ios/App/App/IsolatedModules/JS/JSEvaluator.swift @@ -0,0 +1,167 @@ +// +// JSEvaluator.swift +// App +// +// Created by Julia Samol on 06.02.23. +// + +import Foundation +import Capacitor +import WebKit + +class JSEvaluator { + private let webViewEnv: WebViewEnvironment + private let modulesManager: ModulesManager + + init(fileExplorer: FileExplorer) { + self.webViewEnv = .init(fileExplorer: fileExplorer) + self.modulesManager = .init() + } + + func registerModule(_ module: JSModule, forProtocols protocolIdentifiers: [String]) async { + await modulesManager.registerModule(module, forProtocols: protocolIdentifiers) + } + + func evaluatePreviewModule(_ module: JSModule) async throws -> [String: Any] { + return try await self.webViewEnv.run(.load(.init(protocolType: nil)), in: module) + } + + func evaluateLoadModules(_ modules: [JSModule], for protocolType: JSProtocolType?) async throws -> [String: Any] { + let modulesJSON = try await modules.asyncMap { module -> [String : Any] in + let json = try await self.webViewEnv.run(.load(.init(protocolType: protocolType)), in: module) + try await self.modulesManager.registerModule(module, forJSON: json) + + return json + } + + return ["modules": modulesJSON] + } + + func evaluateCallOfflineProtocolMethod( + _ name: String, + ofProtocol protocolIdentifier: String, + withArgs args: JSArray? + ) async throws -> [String: Any] { + let modules = await modulesManager.modules + guard let module = modules[protocolIdentifier] else { + throw Error.moduleNotFound(protocolIdentifier) + } + + return try await webViewEnv.run( + .callMethod( + .offlineProtocol( + .init(name: name, args: args, protocolIdentifier: protocolIdentifier) + ) + ), + in: module + ) + } + + func evaluateCallOnlineProtocolMethod( + _ name: String, + ofProtocol protocolIdentifier: String, + onNetwork networkID: String?, + withArgs args: JSArray? + ) async throws -> [String: Any] { + let modules = await modulesManager.modules + guard let module = modules[protocolIdentifier] else { + throw Error.moduleNotFound(protocolIdentifier) + } + + return try await webViewEnv.run( + .callMethod( + .onlineProtocol( + .init(name: name, args: args, protocolIdentifier: protocolIdentifier, networkID: networkID) + ) + ), + in: module + ) + } + + func evaluateCallBlockExplorerMethod( + _ name: String, + ofProtocol protocolIdentifier: String, + onNetwork networkID: String?, + withArgs args: JSArray? + ) async throws -> [String: Any] { + let modules = await modulesManager.modules + guard let module = modules[protocolIdentifier] else { + throw Error.moduleNotFound(protocolIdentifier) + } + + return try await webViewEnv.run( + .callMethod( + .blockExplorer( + .init(name: name, args: args, protocolIdentifier: protocolIdentifier, networkID: networkID) + ) + ), + in: module + ) + } + + func evaluateCallV3SerializerCompanionMethod( + _ name: String, + ofModule moduleIdentifier: String, + withArgs args: JSArray? + ) async throws -> [String: Any] { + let modules = await modulesManager.modules + guard let module = modules[moduleIdentifier] else { + throw Error.moduleNotFound(moduleIdentifier) + } + + return try await webViewEnv.run( + .callMethod( + .v3SerializerCompanion( + .init(name: name, args: args) + ) + ), + in: module + ) + } + + func destroy() async throws { + try await webViewEnv.destroy() + } + + private actor ModulesManager { + private(set) var modules: [String: JSModule] = [:] + + func registerModule(_ module: JSModule, forJSON json: [String: Any]) throws { + guard let protocols = json["protocols"] as? [Any] else { + throw Error.invalidJSON + } + + let protocolIdentifiers = try protocols.map { `protocol` -> String in + guard let `protocol` = `protocol` as? [String: Any], let identifier = `protocol`["identifier"] as? String else { + throw Error.invalidJSON + } + + return identifier + } + + registerModule(module, forProtocols: protocolIdentifiers) + } + + func registerModule(_ module: JSModule, forProtocols protocolIdentifiers: [String]) { + modules[module.identifier] = module + protocolIdentifiers.forEach { identifier in modules[identifier] = module } + } + } + + enum Error: Swift.Error { + case moduleNotFound(String) + case invalidJSON + } +} + +private extension JSArray { + func replaceNullWithUndefined() -> JSArray { + map { + if $0 is NSNull { + return JSUndefined.value + } else { + return $0 + } + } + } +} diff --git a/ios/App/App/IsolatedModules/JS/JSModule.swift b/ios/App/App/IsolatedModules/JS/JSModule.swift new file mode 100644 index 00000000..89087cbd --- /dev/null +++ b/ios/App/App/IsolatedModules/JS/JSModule.swift @@ -0,0 +1,276 @@ +// +// JSModule.swift +// App +// +// Created by Julia Samol on 06.02.23. +// + +import Foundation +import Capacitor + +// MARK: JSModule + +enum JSModule { + case asset(Asset) + case installed(Instsalled) + case preview(Preview) + + var identifier: String { + switch self { + case .asset(let asset): + return asset.identifier + case .installed(let installed): + return installed.identifier + case .preview(let preview): + return preview.identifier + } + } + + var namespace: String? { + switch self { + case .asset(let asset): + return asset.namespace + case .installed(let installed): + return installed.namespace + case .preview(let preview): + return preview.namespace + } + } + + var preferredEnvironment: JSEnvironmentKind { + switch self { + case .asset(let asset): + return asset.preferredEnvironment + case .installed(let installed): + return installed.preferredEnvironment + case .preview(let preview): + return preview.preferredEnvironment + } + } + + var sources: [String] { + switch self { + case .asset(let asset): + return asset.sources + case .installed(let installed): + return installed.sources + case .preview(let preview): + return preview.sources + } + } + + struct Asset: JSModuleProtocol { + let identifier: String + let namespace: String? + let preferredEnvironment: JSEnvironmentKind + let sources: [String] + } + + struct Instsalled: JSModuleProtocol { + let identifier: String + let namespace: String? + let preferredEnvironment: JSEnvironmentKind + let sources: [String] + } + + struct Preview: JSModuleProtocol { + let identifier: String + let namespace: String? + let preferredEnvironment: JSEnvironmentKind + let sources: [String] + let path: URL + } +} + +protocol JSModuleProtocol { + var identifier: String { get } + var namespace: String? { get } + var preferredEnvironment: JSEnvironmentKind { get } + var sources: [String] { get } +} + +// MARK: JSProtocolType + +enum JSProtocolType: String, JSONConvertible { + case offline + case online + case full + + func toJSONString() throws -> String { + return try rawValue.toJSONString() + } +} + +// MARK: JSCallMethodTarget + +enum JSCallMethodTarget: String, JSONConvertible { + case offlineProtocol + case onlineProtocol + case blockExplorer + case v3SerializerCompanion + + func toJSONString() throws -> String { + return try rawValue.toJSONString() + } +} + +// MARK: JSModuleAction + +enum JSModuleAction: JSONConvertible { + private static let loadType: String = "load" + private static let callMethodType: String = "callMethod" + + case load(Load) + case callMethod(CallMethod) + + func toJSONString() throws -> String { + switch self { + case .load(let load): + return try load.toJSONString() + case .callMethod(let callMethod): + return try callMethod.toJSONString() + } + } + + struct Load: JSONConvertible { + let protocolType: JSProtocolType? + + func toJSONString() throws -> String { + return """ + { + "type": "\(JSModuleAction.loadType)", + "protocolType": \(try protocolType?.toJSONString() ?? (try JSUndefined.value.toJSONString())) + } + """ + } + } + + enum CallMethod: JSONConvertible { + case offlineProtocol(OfflineProtocol) + case onlineProtocol(OnlineProtocol) + case blockExplorer(BlockExplorer) + case v3SerializerCompanion(V3SerializerCompanion) + + func toJSONString() throws -> String { + switch self { + case .offlineProtocol(let offlineProtocol): + return try offlineProtocol.toJSONString() + case .onlineProtocol(let onlineProtocol): + return try onlineProtocol.toJSONString() + case .blockExplorer(let blockExplorer): + return try blockExplorer.toJSONString() + case .v3SerializerCompanion(let v3SerializerCompanion): + return try v3SerializerCompanion.toJSONString() + } + } + + private static func toJSONStringWithPartial( + target: JSCallMethodTarget, + name: String, + args: JSArray?, + partial partialJSON: String + ) throws -> String { + let args = try args?.replaceNullWithUndefined().toJSONString() ?? "[]" + let objectJSON = """ + { + "type": "\(JSModuleAction.callMethodType)", + "target": \(try target.toJSONString()), + "method": "\(name)", + "args": \(args) + } + """ + + guard let objectData = objectJSON.data(using: .utf8), + let object = try JSONSerialization.jsonObject(with: objectData) as? [String: Any], + let partialData = partialJSON.data(using: .utf8), + let partial = try JSONSerialization.jsonObject(with: partialData) as? [String: Any] else { + throw JSError.invalidJSON + } + + let merged = object.merging(partial, uniquingKeysWith: { $1 }) + guard JSONSerialization.isValidJSONObject(merged) else { + throw JSError.invalidJSON + } + + let data = try JSONSerialization.data(withJSONObject: merged, options: []) + return .init(data: data, encoding: .utf8)! + } + + struct OfflineProtocol: JSONConvertible { + let target: JSCallMethodTarget = .offlineProtocol + let name: String + let args: JSArray? + let protocolIdentifier: String + + func toJSONString() throws -> String { + let partial: String = """ + { + "protocolIdentifier": "\(protocolIdentifier)" + } + """ + + return try CallMethod.toJSONStringWithPartial(target: target, name: name, args: args, partial: partial) + } + } + + struct OnlineProtocol: JSONConvertible { + let target: JSCallMethodTarget = .onlineProtocol + let name: String + let args: JSArray? + let protocolIdentifier: String + let networkID: String? + + func toJSONString() throws -> String { + let partial: String = """ + { + "protocolIdentifier": "\(protocolIdentifier)", + "networkId": \(try networkID?.toJSONString() ?? (try JSUndefined.value.toJSONString())) + } + """ + + return try CallMethod.toJSONStringWithPartial(target: target, name: name, args: args, partial: partial) + } + } + + struct BlockExplorer: JSONConvertible { + let target: JSCallMethodTarget = .blockExplorer + let name: String + let args: JSArray? + let protocolIdentifier: String + let networkID: String? + + func toJSONString() throws -> String { + let partial: String = """ + { + "protocolIdentifier": "\(protocolIdentifier)", + "networkId": \(try networkID?.toJSONString() ?? (try JSUndefined.value.toJSONString())) + } + """ + + return try CallMethod.toJSONStringWithPartial(target: target, name: name, args: args, partial: partial) + } + } + + struct V3SerializerCompanion: JSONConvertible { + let target: JSCallMethodTarget = .v3SerializerCompanion + let name: String + let args: JSArray? + + func toJSONString() throws -> String { + return try CallMethod.toJSONStringWithPartial(target: target, name: name, args: args, partial: "{}") + } + } + } +} + +private extension JSArray { + func replaceNullWithUndefined() -> JSArray { + map { + if $0 is NSNull { + return JSUndefined.value + } else { + return $0 + } + } + } +} diff --git a/ios/App/App/IsolatedModules/ModuleManifest.swift b/ios/App/App/IsolatedModules/ModuleManifest.swift new file mode 100644 index 00000000..ed8c968e --- /dev/null +++ b/ios/App/App/IsolatedModules/ModuleManifest.swift @@ -0,0 +1,31 @@ +// +// ModuleManifest.swift +// App +// +// Created by Julia Samol on 08.02.23. +// + +import Foundation + +struct ModuleManifest: Codable { + let name: String + let version: String + let author: String + let signature: String + let src: Src? + let res: Res? + let include: [String] + let jsenv: JSEnv? + + struct Src: Codable { + let namespace: String? + } + + struct Res: Codable { + let symbol: String? + } + + struct JSEnv: Codable { + let ios: JSEnvironmentKind? + } +} diff --git a/ios/App/App/Zip/Zip.m b/ios/App/App/Zip/Zip.m new file mode 100644 index 00000000..0f67cf99 --- /dev/null +++ b/ios/App/App/Zip/Zip.m @@ -0,0 +1,13 @@ +// +// Zip.m +// App +// +// Created by Julia Samol on 19.01.23. +// + +#import +#import + +CAP_PLUGIN(Zip, "Zip", + CAP_PLUGIN_METHOD(unzip, CAPPluginReturnPromise); +) diff --git a/ios/App/App/Zip/Zip.swift b/ios/App/App/Zip/Zip.swift new file mode 100644 index 00000000..da74391f --- /dev/null +++ b/ios/App/App/Zip/Zip.swift @@ -0,0 +1,76 @@ +// +// Zip.swift +// App +// +// Created by Julia Samol on 19.01.23. +// + +import Foundation +import Capacitor +import ZIPFoundation + +@objc(Zip) +public class Zip: CAPPlugin { + + @objc func unzip(_ call: CAPPluginCall) { + call.assertReceived(forMethod: "unzip", requiredParams: Param.FROM, Param.TO) + + do { + guard let sourceURL = getFileURL(at: call.from, locatedIn: call.directory) else { + throw Error.invalidPath("from") + } + + guard let destinationURL = getFileURL(at: call.to, locatedIn: call.toDirectory) else { + throw Error.invalidPath("to") + } + + try unzip(from: sourceURL, to: destinationURL) + call.resolve() + } catch { + call.reject("Error: \(error)") + } + } + + private func unzip(from sourceURL: URL, to destinationURL: URL) throws { + try FileManager.default.createDirectory(at: destinationURL, withIntermediateDirectories: true) + try FileManager.default.unzipItem(at: sourceURL, to: destinationURL) + } + + private func getFileURL(at path: String, locatedIn directory: Directory?) -> URL? { + if let directory = FileManager.default.getDirectory(from: directory) { + guard let dir = FileManager.default.urls(for: directory, in: .userDomainMask).first else { + return nil + } + + return !path.isEmpty ? dir.appendingPathComponent(path) : dir + } else { + return URL(string: path) + } + } + + struct Param { + static let FROM = "from" + static let TO = "to" + static let DIRECTORY = "directory" + static let TO_DIRECTORY = "toDirectory" + } + + private enum Error: Swift.Error { + case invalidPath(String) + } +} + +private extension CAPPluginCall { + var from: String { return getString(Zip.Param.FROM)! } + var to: String { return getString(Zip.Param.TO)! } + + var directory: Directory? { + guard let directory = getString(Zip.Param.DIRECTORY) else { return nil } + return .init(rawValue: directory) + } + + var toDirectory: Directory? { + guard let toDirectory = getString(Zip.Param.TO_DIRECTORY) else { return nil } + return .init(rawValue: toDirectory) + } +} diff --git a/ios/App/Podfile b/ios/App/Podfile index 39871475..9d1e4d89 100644 --- a/ios/App/Podfile +++ b/ios/App/Podfile @@ -17,12 +17,14 @@ def capacitor_pods pod 'CapacitorFilesystem', :path => '../../node_modules/@capacitor/filesystem' pod 'CapacitorSplashScreen', :path => '../../node_modules/@capacitor/splash-screen' pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar' + pod 'CapawesomeCapacitorFilePicker', :path => '../../node_modules/@capawesome/capacitor-file-picker' pod 'CordovaPlugins', :path => '../capacitor-cordova-ios-plugins' end target 'App' do capacitor_pods # Add your Pods here + pod 'ZIPFoundation', '~> 0.9' end diff --git a/package.json b/package.json index 25a67700..0ceae744 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,8 @@ "lint-ci": "ng lint app --format json > ./lintReport.json || true", "lint-fix": "tslint --fix --project tsconfig.json", "e2e": "ng e2e", - "postinstall": "jetifier && node apply-diagnostic-modules.js && node fix-qrscanner-gradle.js && yarn browserify-coinlib", + "postinstall": "jetifier && node apply-diagnostic-modules.js && node fix-qrscanner-gradle.js && node copy-builtin-modules.js", "sonar-scanner": "sonar-scanner", - "browserify-coinlib": "browserify ./node_modules/@airgap/coinlib-core/index.js -s airgapCoinLib -o ./src/assets/libs/airgap-coin-lib.browserify.js", "prettier": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"", "remove-sapling": "replace './assets/sapling/sapling-' './assets/no-sapling-web/sapling-' ./src/app/app.component.ts", "prepare-prod-build": "yarn configure-mangle", @@ -37,24 +36,46 @@ "install-build-dependencies": "node install-build-deps.js", "apply-diagnostic-modules": "node apply-diagnostic-modules.js" }, + "resolutions": { + "@airgap/aeternity": "0.13.11", + "@airgap/astar": "0.13.11", + "@airgap/bitcoin": "0.13.11", + "@airgap/coinlib-core": "0.13.11", + "@airgap/coreum": "0.13.11", + "@airgap/cosmos": "0.13.11", + "@airgap/cosmos-core": "0.13.11", + "@airgap/crypto": "0.13.11", + "@airgap/ethereum": "0.13.11", + "@airgap/groestlcoin": "0.13.11", + "@airgap/icp": "0.13.11", + "@airgap/module-kit": "0.13.11", + "@airgap/moonbeam": "0.13.11", + "@airgap/polkadot": "0.13.11", + "@airgap/serializer": "0.13.11", + "@airgap/substrate": "0.13.11", + "@airgap/tezos": "0.13.11" + }, "dependencies": { - "@airgap/aeternity": "0.13.10", - "@airgap/angular-core": "0.0.34", - "@airgap/angular-ngrx": "0.0.34", - "@airgap/astar": "0.13.10", - "@airgap/bitcoin": "0.13.10", - "@airgap/coinlib-core": "0.13.10", - "@airgap/cosmos": "0.13.10", - "@airgap/ethereum": "0.13.10", - "@airgap/groestlcoin": "0.13.10", - "@airgap/icp": "0.13.10", - "@airgap/module-kit": "0.13.10", - "@airgap/moonbeam": "0.13.10", - "@airgap/polkadot": "0.13.10", + "@airgap/aeternity": "0.13.11", + "@airgap/angular-core": "0.0.35", + "@airgap/angular-ngrx": "0.0.35", + "@airgap/astar": "0.13.11", + "@airgap/bitcoin": "0.13.11", + "@airgap/coinlib-core": "0.13.11", + "@airgap/coreum": "0.13.11", + "@airgap/cosmos": "0.13.11", + "@airgap/cosmos-core": "0.13.11", + "@airgap/crypto": "0.13.11", + "@airgap/ethereum": "0.13.11", + "@airgap/groestlcoin": "0.13.11", + "@airgap/icp": "0.13.11", + "@airgap/module-kit": "0.13.11", + "@airgap/moonbeam": "0.13.11", + "@airgap/polkadot": "0.13.11", "@airgap/sapling-wasm": "0.0.7", - "@airgap/serializer": "0.13.10", - "@airgap/substrate": "0.13.10", - "@airgap/tezos": "0.13.10", + "@airgap/serializer": "0.13.11", + "@airgap/substrate": "0.13.11", + "@airgap/tezos": "0.13.11", "@angular/common": "13.2.5", "@angular/core": "13.2.5", "@angular/forms": "13.2.5", @@ -70,6 +91,7 @@ "@capacitor/ios": "^4.0.0", "@capacitor/splash-screen": "^4.0.0", "@capacitor/status-bar": "^4.0.0", + "@capawesome/capacitor-file-picker": "^0.5.8", "@download/blockies": "1.0.3", "@ethereumjs/tx": "^3.4.0", "@ionic-native/core": "5.36.0", @@ -127,15 +149,38 @@ "@capacitor/cli": "3.2.5", "@ionic/angular-toolkit": "6.0.0", "@ionic/cli": "6.18.2", + "@types/core-js": "^2.5.0", "@types/emscripten": "^1.39.6", + "@types/jasmine": "~2.8.8", + "@types/jasminewd2": "~2.0.3", "@types/node": "17.0.21", "browserify": "^17.0.0", + "codelyzer": "~4.5.0", "crypto-browserify": "3.12.0", - "jetifier": "1.6.6", + "electron-builder": "^20.43.0", + "husky": "^7.0.0", + "jasmine-core": "~3.9.0", + "jasmine-spec-reporter": "~7.0.0", + "jetifier": "^1.6.6", + "karma": "~6.3.4", + "karma-chrome-launcher": "~3.1.0", + "karma-coverage": "^2.0.3", + "karma-jasmine": "~4.0.1", + "karma-jasmine-html-reporter": "^1.7.0", + "karma-spec-reporter": "0.0.32", "path-browserify": "1.0.1", + "prettier": "2.0.5", + "pretty-quick": "^1.11.0", + "protractor": "~7.0.0", + "puppeteer": "^10.2.0", "replace": "1.2.1", "sonarqube-scanner": "2.8.1", "stream-browserify": "3.0.0", + "ts-node": "9.1.1", + "tslint": "6.1.3", + "tslint-config-prettier": "1.18.0", + "tslint-config-valorsoft": "2.2.1", + "tslint-plugin-prettier": "2.3.0", "typescript": "4.4.4" }, "buildDependencies": { diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 51f484c0..11154fd7 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -98,6 +98,22 @@ const routes: Routes = [ (m) => m.SocialRecoveryValidateSharePageModule ) }, + { + path: 'contact-book-contacts', + loadChildren: () => import('./pages/contact-book-contacts/contact-book-contacts.module').then((m) => m.ContactBookContactsPageModule) + }, + { + path: 'contact-book-contacts-detail', + loadChildren: () => import('./pages/contact-book-contacts-detail/contact-book-contacts-detail.module').then((m) => m.ContactBookContactsDetailPageModule) + }, + { + path: 'contact-book-onboarding', + loadChildren: () => import('./pages/contact-book-onboarding/contact-book-onboarding.module').then((m) => m.ContactBookOnboardingPageModule) + }, + { + path: 'contact-book-settings', + loadChildren: () => import('./pages/contact-book-settings/contact-book-settings.module').then((m) => m.ContactBookOnboardingPageModule) + }, { path: 'deserialized-detail', loadChildren: () => import('./pages/deserialized-detail/deserialized-detail.module').then((m) => m.DeserializedDetailPageModule) @@ -158,6 +174,10 @@ const routes: Routes = [ { path: 'address-explorer', loadChildren: () => import('./pages/address-explorer/address-explorer.module').then((m) => m.AddressExplorerPageModule) + }, + { + path: 'module-preview', + loadChildren: () => import('./pages/module-preview/module-preview.module').then((m) => m.ModulePreviewPageModule) } ] diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index ca9c4dd1..f3e86b2e 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,8 +1,9 @@ -import { APP_PLUGIN, CLIPBOARD_PLUGIN, ProtocolService, SPLASH_SCREEN_PLUGIN, STATUS_BAR_PLUGIN } from '@airgap/angular-core' +import { APP_PLUGIN, CLIPBOARD_PLUGIN, FILESYSTEM_PLUGIN, IsolatedModulesPlugin, ISOLATED_MODULES_PLUGIN, ProtocolService, SPLASH_SCREEN_PLUGIN, STATUS_BAR_PLUGIN, ZipPlugin, ZIP_PLUGIN } from '@airgap/angular-core' import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core' import { ComponentFixture, TestBed } from '@angular/core/testing' import { AppPlugin } from '@capacitor/app' import { ClipboardPlugin } from '@capacitor/clipboard' +import { FilesystemPlugin } from '@capacitor/filesystem' import { SplashScreenPlugin } from '@capacitor/splash-screen' import { StatusBarPlugin } from '@capacitor/status-bar' import { Platform } from '@ionic/angular' @@ -10,10 +11,13 @@ import { TranslateService } from '@ngx-translate/core' import { createAppSpy, createClipboardSpy, + createFilesystemSpy, + createIsolatedModulesSpy, createSaplingSpy, createSecurityUtilsSpy, createSplashScreenSpy, - createStatusBarSpy + createStatusBarSpy, + createZipSpy } from 'test-config/plugins-mocks' import { UnitHelper } from './../../test-config/unit-test-helper' @@ -34,6 +38,9 @@ describe('AppComponent', () => { let statusBarSpy: StatusBarPlugin let splashScreenSpy: SplashScreenPlugin let clipboardSpy: ClipboardPlugin + let filesystemSpy: FilesystemPlugin + let zipSpy: ZipPlugin + let isolatedModulesSpy: IsolatedModulesPlugin let platformReadySpy: Promise let platformSpy: Platform // let component: AppComponent @@ -46,6 +53,9 @@ describe('AppComponent', () => { statusBarSpy = createStatusBarSpy() splashScreenSpy = createSplashScreenSpy() clipboardSpy = createClipboardSpy() + filesystemSpy = createFilesystemSpy() + zipSpy = createZipSpy() + isolatedModulesSpy = createIsolatedModulesSpy() platformReadySpy = Promise.resolve() platformSpy = jasmine.createSpyObj('Platform', { ready: platformReadySpy }) @@ -62,6 +72,9 @@ describe('AppComponent', () => { { provide: STATUS_BAR_PLUGIN, useValue: statusBarSpy }, { provide: SPLASH_SCREEN_PLUGIN, useValue: splashScreenSpy }, { provide: CLIPBOARD_PLUGIN, useValue: clipboardSpy }, + { provide: FILESYSTEM_PLUGIN, useValue: filesystemSpy }, + { provide: ZIP_PLUGIN, useValue: zipSpy }, + { provide: ISOLATED_MODULES_PLUGIN, useValue: isolatedModulesSpy }, { provide: Platform, useValue: platformSpy }, StartupChecksService, IACService, diff --git a/src/app/app.component.ts b/src/app/app.component.ts index bae3c20d..d85482bc 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { APP_PLUGIN, IACMessageTransport, ProtocolService, SPLASH_SCREEN_PLUGIN, STATUS_BAR_PLUGIN } from '@airgap/angular-core' +import { APP_PLUGIN, IACMessageTransport, IsolatedModulesService, ProtocolService, SPLASH_SCREEN_PLUGIN, STATUS_BAR_PLUGIN } from '@airgap/angular-core' import { MainProtocolSymbols } from '@airgap/coinlib-core' import { TezosSaplingExternalMethodProvider, @@ -23,7 +23,6 @@ import { MnemonicSecret } from './models/secret' import { ErrorCategory, handleErrorLocal } from './services/error-handler/error-handler.service' import { IACService } from './services/iac/iac.service' import { NavigationService } from './services/navigation/navigation.service' -import { ProtocolModuleService } from './services/protocol-module/protocol-module.service' import { SaplingNativeService } from './services/sapling-native/sapling-native.service' import { SecretsService } from './services/secrets/secrets.service' import { StartupChecksService } from './services/startup-checks/startup-checks.service' @@ -57,7 +56,7 @@ export class AppComponent implements AfterViewInit { private readonly navigationService: NavigationService, private readonly httpClient: HttpClient, private readonly saplingNativeService: SaplingNativeService, - private readonly protocolModuleService: ProtocolModuleService, + private readonly isolatedModuleService: IsolatedModulesService, @Inject(APP_PLUGIN) private readonly app: AppPlugin, @Inject(SECURITY_UTILS_PLUGIN) private readonly securityUtils: SecurityUtilsPlugin, @Inject(SPLASH_SCREEN_PLUGIN) private readonly splashScreen: SplashScreenPlugin, @@ -127,14 +126,17 @@ export class AppComponent implements AfterViewInit { } private async initializeTranslations(): Promise { + this.translateService.setDefaultLang(LanguagesType.EN) + const savedLanguage = await this.storageService.get(VaultStorageKey.LANGUAGE_TYPE) const deviceLanguage = this.translateService.getBrowserLang() - const currentLanguage = savedLanguage || (deviceLanguage as LanguagesType) || LanguagesType.EN + const currentLanguage = savedLanguage || (deviceLanguage as LanguagesType) + await this.translateService.use(currentLanguage).toPromise() } private async initializeProtocols(): Promise { - const protocols = await this.protocolModuleService.loadProtocols([MainProtocolSymbols.XTZ_SHIELDED]) + const protocols = await this.isolatedModuleService.loadProtocols('offline', [MainProtocolSymbols.XTZ_SHIELDED]) const externalMethodProvider: TezosSaplingExternalMethodProvider | undefined = await this.saplingNativeService.createExternalMethodProvider() diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 0a7142af..26846348 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -15,7 +15,11 @@ import { SPLASH_SCREEN_PLUGIN, STATUS_BAR_PLUGIN, FILESYSTEM_PLUGIN, - UiEventService + UiEventService, + IsolatedModules, + ISOLATED_MODULES_PLUGIN, + Zip, + ZIP_PLUGIN } from '@airgap/angular-core' import { AirGapAngularNgRxModule, currencySymbolNgRxFacade } from '@airgap/angular-ngrx' import { PercentPipe } from '@angular/common' @@ -28,6 +32,7 @@ import { AppLauncher } from '@capacitor/app-launcher' import { Clipboard } from '@capacitor/clipboard' import { SplashScreen } from '@capacitor/splash-screen' import { StatusBar } from '@capacitor/status-bar' +import { FilePicker } from '@capawesome/capacitor-file-picker' import { DeviceMotion } from '@ionic-native/device-motion/ngx' import { Diagnostic } from '@ionic-native/diagnostic/ngx' import { IonicModule, IonicRouteStrategy, Platform } from '@ionic/angular' @@ -39,8 +44,8 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core' import { AppRoutingModule } from './app-routing.module' import { AppComponent } from './app.component' import * as fromRoot from './app.reducers' -import { CameraPreview, IsolatedProtocol, SaplingNative, SecurityUtils } from './capacitor-plugins/definitions' -import { CAMERA_PREVIEW_PLUGIN, ISOLATED_PROTOCOL_PLUGIN, SAPLING_PLUGIN, SECURITY_UTILS_PLUGIN } from './capacitor-plugins/injection-tokens' +import { CameraPreview, SaplingNative, SecurityUtils } from './capacitor-plugins/definitions' +import { CAMERA_PREVIEW_PLUGIN, FILE_PICKER_PLUGIN, SAPLING_PLUGIN, SECURITY_UTILS_PLUGIN } from './capacitor-plugins/injection-tokens' import { appConfig } from './config/app-config' import { DistributionOnboardingPageModule } from './pages/distribution-onboarding/distribution-onboarding.module' import { IntroductionPageModule } from './pages/introduction/introduction.module' @@ -125,8 +130,10 @@ export function createTranslateLoader(http: HttpClient): AirGapTranslateLoader { { provide: SECURITY_UTILS_PLUGIN, useValue: SecurityUtils }, { provide: SPLASH_SCREEN_PLUGIN, useValue: SplashScreen }, { provide: STATUS_BAR_PLUGIN, useValue: StatusBar }, - { provide: ISOLATED_PROTOCOL_PLUGIN, useValue: IsolatedProtocol }, { provide: APP_CONFIG, useValue: appConfig }, + { provide: ZIP_PLUGIN, useValue: Zip }, + { provide: FILE_PICKER_PLUGIN, useValue: FilePicker }, + { provide: ISOLATED_MODULES_PLUGIN, useValue: IsolatedModules }, { provide: ErrorHandler, useClass: ErrorHandlerService }, Diagnostic, { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, diff --git a/src/app/capacitor-plugins/definitions.ts b/src/app/capacitor-plugins/definitions.ts index 143a1a9e..dd25acbe 100644 --- a/src/app/capacitor-plugins/definitions.ts +++ b/src/app/capacitor-plugins/definitions.ts @@ -1,5 +1,3 @@ -import { ICoinProtocol } from '@airgap/coinlib-core' -import { ProtocolOptions } from '@airgap/coinlib-core/utils/ProtocolOptions' import { PluginListenerHandle, registerPlugin } from '@capacitor/core' export interface CameraPreviewPlugin { @@ -60,20 +58,3 @@ export interface SecurityUtilsPlugin { } export const SecurityUtils: SecurityUtilsPlugin = registerPlugin('SecurityUtils') - -export interface IsolatedProtocolPlugin { - getField(params: { - identifier: string, - options?: ProtocolOptions, - key: keyof ICoinProtocol - }): Promise<{ result: unknown }> - - callMethod(params: { - identifier: string, - options?: ProtocolOptions, - key: keyof ICoinProtocol, - args?: unknown[] - }): Promise<{ result: unknown }> -} - -export const IsolatedProtocol: IsolatedProtocolPlugin = registerPlugin('IsolatedProtocol') \ No newline at end of file diff --git a/src/app/capacitor-plugins/injection-tokens.ts b/src/app/capacitor-plugins/injection-tokens.ts index e93488cd..c693cb63 100644 --- a/src/app/capacitor-plugins/injection-tokens.ts +++ b/src/app/capacitor-plugins/injection-tokens.ts @@ -1,7 +1,8 @@ import { InjectionToken } from '@angular/core' -import { CameraPreviewPlugin, IsolatedProtocolPlugin, SaplingNativePlugin, SecurityUtilsPlugin } from './definitions' +import { FilePickerPlugin } from '@capawesome/capacitor-file-picker' +import { CameraPreviewPlugin, SaplingNativePlugin, SecurityUtilsPlugin } from './definitions' export const CAMERA_PREVIEW_PLUGIN = new InjectionToken('CameraPreviewPlugin') export const SAPLING_PLUGIN = new InjectionToken('SaplingPlugin') export const SECURITY_UTILS_PLUGIN = new InjectionToken('SecurityUtilsPlugin') -export const ISOLATED_PROTOCOL_PLUGIN = new InjectionToken('IsolatedProtocolPlugin') +export const FILE_PICKER_PLUGIN = new InjectionToken('FilePickerPlugin') \ No newline at end of file diff --git a/src/app/components/components.module.ts b/src/app/components/components.module.ts index 62e23925..1885860d 100644 --- a/src/app/components/components.module.ts +++ b/src/app/components/components.module.ts @@ -10,6 +10,7 @@ import { PipesModule } from '../pipes/pipes.module' import { EntropyProgressComponent } from './entropy-progress/entropy-progress.component' import { GridInputComponent } from './grid-input/grid-input.component' +import { KeyboardPopoverComponent } from './keyboard-popover/keyboard-popover.component' import { MessageSignRequestComponent } from './message-sign-request/message-sign-request.component' import { MessageSignResponseComponent } from './message-sign-response/message-sign-response.component' import { ProgressFooterComponent } from './progress-footer/progress-footer.component' @@ -36,7 +37,8 @@ import { VerifyKeyComponent } from './verify-key/verify-key.component' MessageSignRequestComponent, MessageSignResponseComponent, GridInputComponent, - SecretOptionItemComponent + SecretOptionItemComponent, + KeyboardPopoverComponent ], imports: [IonicModule, PipesModule, CommonModule, FormsModule, TranslateModule, QRCodeModule, AirGapAngularCoreModule], exports: [ @@ -52,7 +54,8 @@ import { VerifyKeyComponent } from './verify-key/verify-key.component' MessageSignRequestComponent, MessageSignResponseComponent, GridInputComponent, - SecretOptionItemComponent + SecretOptionItemComponent, + KeyboardPopoverComponent ], entryComponents: [] }) diff --git a/src/app/components/keyboard-popover/keyboard-popover.component.html b/src/app/components/keyboard-popover/keyboard-popover.component.html new file mode 100644 index 00000000..7772b7b9 --- /dev/null +++ b/src/app/components/keyboard-popover/keyboard-popover.component.html @@ -0,0 +1,25 @@ + + + + {{ 'keyboard.add' | translate }} + + + + {{ 'keyboard.delete' | translate }} + + + + + {{ 'keyboard.shuffle' | translate }} + + + + + {{ 'keyboard.mask' | translate }} + + + + + {{ 'keyboard.word_list' | translate }} + + diff --git a/src/app/components/keyboard-popover/keyboard-popover.component.scss b/src/app/components/keyboard-popover/keyboard-popover.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/components/keyboard-popover/keyboard-popover.component.spec.ts b/src/app/components/keyboard-popover/keyboard-popover.component.spec.ts new file mode 100644 index 00000000..cb553d53 --- /dev/null +++ b/src/app/components/keyboard-popover/keyboard-popover.component.spec.ts @@ -0,0 +1,24 @@ +// import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +// import { IonicModule } from '@ionic/angular'; + +// import { KeyboardPopoverComponent } from './keyboard-popover.component'; + +// describe('KeyboardPopoverComponent', () => { +// let component: KeyboardPopoverComponent; +// let fixture: ComponentFixture; + +// beforeEach(waitForAsync(() => { +// TestBed.configureTestingModule({ +// declarations: [ KeyboardPopoverComponent ], +// imports: [IonicModule.forRoot()] +// }).compileComponents(); + +// fixture = TestBed.createComponent(KeyboardPopoverComponent); +// component = fixture.componentInstance; +// fixture.detectChanges(); +// })); + +// it('should create', () => { +// expect(component).toBeTruthy(); +// }); +// }); diff --git a/src/app/components/keyboard-popover/keyboard-popover.component.ts b/src/app/components/keyboard-popover/keyboard-popover.component.ts new file mode 100644 index 00000000..d3c81e0b --- /dev/null +++ b/src/app/components/keyboard-popover/keyboard-popover.component.ts @@ -0,0 +1,56 @@ +import { Component, OnInit } from '@angular/core' + +@Component({ + selector: 'airgap-keyboard-popover', + templateUrl: './keyboard-popover.component.html', + styleUrls: ['./keyboard-popover.component.scss'] +}) +export class KeyboardPopoverComponent implements OnInit { + private readonly onAdd: Function + private readonly onClick: Function + private readonly onDelete: Function + private readonly onScramble: Function + private readonly onShowWordlist: Function + private readonly onToggleShuffled: Function + + public maskWords: boolean = false + + constructor() {} + + ngOnInit() {} + + add() { + if (this.onAdd) { + this.onAdd() + this.onClick() + } + } + + delete() { + if (this.onDelete) { + this.onDelete() + this.onClick() + } + } + + scramble() { + if (this.onScramble) { + this.onScramble() + this.onClick() + } + } + + showWordlist() { + if (this.onShowWordlist) { + this.onClick() + this.onShowWordlist() + } + } + + toggleShuffled() { + if (this.onToggleShuffled) { + this.onToggleShuffled() + this.onClick() + } + } +} diff --git a/src/app/components/mnemonic-keyboard/mnemonic-keyboard.component.html b/src/app/components/mnemonic-keyboard/mnemonic-keyboard.component.html index a146dc5f..2b8f6d06 100644 --- a/src/app/components/mnemonic-keyboard/mnemonic-keyboard.component.html +++ b/src/app/components/mnemonic-keyboard/mnemonic-keyboard.component.html @@ -43,10 +43,11 @@
- - - - - - + + + {{ 'keyboard.paste' | translate }} + + + +
diff --git a/src/app/components/mnemonic-keyboard/mnemonic-keyboard.component.ts b/src/app/components/mnemonic-keyboard/mnemonic-keyboard.component.ts index 9d7402a8..8692925c 100644 --- a/src/app/components/mnemonic-keyboard/mnemonic-keyboard.component.ts +++ b/src/app/components/mnemonic-keyboard/mnemonic-keyboard.component.ts @@ -1,11 +1,12 @@ import { ClipboardService } from '@airgap/angular-core' import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core' -import { ModalController } from '@ionic/angular' +import { ModalController, PopoverController } from '@ionic/angular' import * as bip39 from 'bip39' import { Observable, Subscription } from 'rxjs' import { WordlistPage } from 'src/app/pages/wordlist/wordlist.page' import { ErrorCategory, handleErrorLocal } from 'src/app/services/error-handler/error-handler.service' +import { KeyboardPopoverComponent } from '../keyboard-popover/keyboard-popover.component' function shuffle(arr: string): string { const array = arr.split('') @@ -69,7 +70,11 @@ export class MnemonicKeyboardComponent implements OnInit, OnDestroy { private subscriptions: Subscription = new Subscription() - constructor(private readonly clipboardService: ClipboardService, private readonly modalController: ModalController) { + constructor( + private readonly clipboardService: ClipboardService, + private readonly modalController: ModalController, + private readonly popoverCtrl: PopoverController + ) { this.paintKeyboard() } @@ -193,4 +198,35 @@ export class MnemonicKeyboardComponent implements OnInit, OnDestroy { modal.present().catch(handleErrorLocal(ErrorCategory.IONIC_MODAL)) } + + public async presentPopover(event: Event): Promise { + const popover = await this.popoverCtrl.create({ + component: KeyboardPopoverComponent, + componentProps: { + onClick: (): void => { + popover.dismiss().catch(handleErrorLocal(ErrorCategory.IONIC_MODAL)) + }, + onAdd: (): void => { + this.add() + }, + onDelete: (): void => { + this.delete() + }, + onScramble: (): void => { + this.scramble() + }, + onShowWordlist: (): void => { + this.showWordlist() + }, + onToggleShuffled: (): void => { + this.toggleShuffled() + }, + maskWords: this._maskInput + }, + event, + translucent: true + }) + + popover.present().catch(handleErrorLocal(ErrorCategory.IONIC_MODAL)) + } } diff --git a/src/app/components/secret-item/secret-item.component.html b/src/app/components/secret-item/secret-item.component.html index 42f86a67..022a4fd3 100644 --- a/src/app/components/secret-item/secret-item.component.html +++ b/src/app/components/secret-item/secret-item.component.html @@ -26,14 +26,6 @@
- - - - - - - - diff --git a/src/app/components/signed-transaction/signed-transaction.component.html b/src/app/components/signed-transaction/signed-transaction.component.html index 519c6444..20fe2809 100644 --- a/src/app/components/signed-transaction/signed-transaction.component.html +++ b/src/app/components/signed-transaction/signed-transaction.component.html @@ -32,6 +32,22 @@
{{ aggregatedInfo.totalFees.toFixed() | feeConverter: { protocol: airGapTxs[ + +
+

This address is not in your address book:

+
+ + {{ address }} +
+

Do you want to add it?

+
+ No + Yes +
+ No, disable address book feature +
+
+ diff --git a/src/app/components/signed-transaction/signed-transaction.component.scss b/src/app/components/signed-transaction/signed-transaction.component.scss index e69de29b..3bdc3d16 100644 --- a/src/app/components/signed-transaction/signed-transaction.component.scss +++ b/src/app/components/signed-transaction/signed-transaction.component.scss @@ -0,0 +1,50 @@ +.suggestion-wrapper { + display: flex; + flex-direction: column; + border: 1px solid var(--ion-color-primary); + padding: 12px; + border-radius: 12px; + + p { + margin-top: 0px; + color: var(--ion-color-primary); + margin-bottom: 12px; + font-weight: 500; + } + + span { + color: white; + } + + .divider { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 12px; + + span { + flex: 1; + line-break: anywhere; + font-size: 14px; + font-weight: 600; + } + + .image { + width: 50px; + height: 50px; + } + } + + .divider-buttons { + display: flex; + align-items: center; + gap: 4px; + } + + ion-button { + flex: 1; + font-size: 14px; + --padding-bottom: 12px; + --padding-top: 12px; + } +} diff --git a/src/app/components/signed-transaction/signed-transaction.component.spec.ts b/src/app/components/signed-transaction/signed-transaction.component.spec.ts index 406e27e2..a002a27e 100644 --- a/src/app/components/signed-transaction/signed-transaction.component.spec.ts +++ b/src/app/components/signed-transaction/signed-transaction.component.spec.ts @@ -7,6 +7,7 @@ import { IACMessageType, Message, Serializer } from '@airgap/serializer' import { SecretsService } from 'src/app/services/secrets/secrets.service' import { SecureStorageService } from 'src/app/services/secure-storage/secure-storage.service' import { SecureStorageServiceMock } from 'src/app/services/secure-storage/secure-storage.mock' +import { ISOLATED_MODULES_PLUGIN, WebIsolatedModules } from '@airgap/angular-core' describe('SignedTransactionComponent', () => { let signedTransactionFixture: ComponentFixture @@ -18,7 +19,11 @@ describe('SignedTransactionComponent', () => { TestBed.configureTestingModule( unitHelper.testBed({ declarations: [], - providers: [{ provide: SecureStorageService, useClass: SecureStorageServiceMock }, SecretsService] + providers: [ + { provide: SecureStorageService, useClass: SecureStorageServiceMock }, + { provide: ISOLATED_MODULES_PLUGIN, useValue: new WebIsolatedModules() }, + SecretsService + ] }) ) .compileComponents() diff --git a/src/app/components/signed-transaction/signed-transaction.component.ts b/src/app/components/signed-transaction/signed-transaction.component.ts index d2ac3d36..0c39c2e1 100644 --- a/src/app/components/signed-transaction/signed-transaction.component.ts +++ b/src/app/components/signed-transaction/signed-transaction.component.ts @@ -1,17 +1,15 @@ import { ProtocolService, SerializerService, sumAirGapTxValues } from '@airgap/angular-core' import { Component, Input } from '@angular/core' -import { - IAirGapTransaction, - ICoinProtocol, - MainProtocolSymbols, - ProtocolSymbols, - SignedTransaction -} from '@airgap/coinlib-core' +import { IAirGapTransaction, ICoinProtocol, MainProtocolSymbols, ProtocolSymbols, SignedTransaction } from '@airgap/coinlib-core' import BigNumber from 'bignumber.js' import { TokenService } from 'src/app/services/token/TokenService' import { SecretsService } from 'src/app/services/secrets/secrets.service' import { IACMessageDefinitionObjectV3 } from '@airgap/serializer' import { TezosSaplingProtocol } from '@airgap/tezos' +import { NavigationService } from 'src/app/services/navigation/navigation.service' +import { ContactsService } from 'src/app/services/contacts/contacts.service' +import { ErrorCategory, handleErrorLocal } from 'src/app/services/error-handler/error-handler.service' +import { AddType } from 'src/app/services/contacts/contacts.service' @Component({ selector: 'airgap-signed-transaction', @@ -25,6 +23,7 @@ export class SignedTransactionComponent { @Input() public syncProtocolString: string + public addressesNotOnContactBook: string[] = [] public airGapTxs: IAirGapTransaction[] public fallbackActivated: boolean = false public rawTxData: string @@ -40,7 +39,9 @@ export class SignedTransactionComponent { private readonly protocolService: ProtocolService, private readonly serializerService: SerializerService, private readonly tokenService: TokenService, - private readonly secretsService: SecretsService + private readonly secretsService: SecretsService, + private readonly navigationService: NavigationService, + private readonly contactsService: ContactsService ) { // } @@ -103,6 +104,43 @@ export class SignedTransactionComponent { this.rawTxData = (this.signedTxs[0].payload as SignedTransaction).transaction } } + + this.checkAdressesNames() + } + + public async checkAdressesNames() { + // Check for addresses in contact book + if (this.airGapTxs && this.airGapTxs.length > 0) { + const isBookenabled = await this.contactsService.isBookEnabled() + if (isBookenabled) { + this.addressesNotOnContactBook = [] + for (let i = 0; i < this.airGapTxs.length; i++) { + this.airGapTxs[i].extra = { names: {} } + const transaction = this.airGapTxs[i] + const toAddresses = transaction.to + for (let j = 0; j < toAddresses.length; j++) { + const toAddress = toAddresses[j] + const hasContactBookAddress = await this.contactsService.isAddressInContacts(toAddress) + if (!hasContactBookAddress) this.addressesNotOnContactBook.push(toAddress) + else { + const name = await this.contactsService.getContactName(toAddress) + if (name) this.airGapTxs[i].extra.names[toAddress] = name + } + } + const fromAddresses = transaction.from + for (let j = 0; j < fromAddresses.length; j++) { + const fromAddress = fromAddresses[j] + const hasContactBookAddress = await this.contactsService.isAddressInContacts(fromAddress) + if (!hasContactBookAddress && !this.addressesNotOnContactBook.includes(fromAddress)) + this.addressesNotOnContactBook.push(fromAddress) + else { + const name = await this.contactsService.getContactName(fromAddress) + if (name) this.airGapTxs[i].extra.names[fromAddress] = name + } + } + } + } + } } private async checkIfSaplingTransaction(transaction: SignedTransaction, protocolIdentifier: ProtocolSymbols): Promise { @@ -116,7 +154,7 @@ export class SignedTransactionComponent { // TODO: find better way to check if `transaction` is a Sapling transaction return recipients.some((recipient: string) => recipient.startsWith('zet') || recipient.toLocaleLowerCase() === 'shielded pool') - } catch(error) { + } catch (error) { console.error(error) return false } @@ -128,4 +166,23 @@ export class SignedTransactionComponent { private async getSaplingProtocol(): Promise { return (await this.protocolService.getProtocol(MainProtocolSymbols.XTZ_SHIELDED)) as TezosSaplingProtocol } + + async onClickAddContact(address: string) { + this.navigationService + .routeWithState('/contact-book-contacts-detail', { isNew: true, address, addType: AddType.SIGNING }) + .catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } + + async onClickDontAddContact(address: string) { + await this.contactsService.addSuggestion(address) + const index = this.addressesNotOnContactBook.findIndex((address) => address === address) + if (index >= 0) { + this.addressesNotOnContactBook.splice(index, 1) + } + } + + async onClickDisableContact() { + await this.contactsService.setBookEnable(false) + this.addressesNotOnContactBook = [] + } } diff --git a/src/app/components/transaction/transaction.component.ts b/src/app/components/transaction/transaction.component.ts index 58568516..39f376ab 100644 --- a/src/app/components/transaction/transaction.component.ts +++ b/src/app/components/transaction/transaction.component.ts @@ -1,6 +1,7 @@ import { IAirGapTransaction, ProtocolSymbols } from '@airgap/coinlib-core' import { Component, Input, OnInit } from '@angular/core' import { Observable } from 'rxjs' +import { ContactsService } from 'src/app/services/contacts/contacts.service' import { AggregatedDetails, TransactionStore } from './transaction.store' @@ -18,7 +19,7 @@ export class TransactionComponent implements OnInit { public airGapTxs$: Observable public aggregatedDetails$: Observable - constructor(private readonly store: TransactionStore) { + constructor(private readonly store: TransactionStore, private readonly contactsService: ContactsService) { this.protocolIdentifier$ = this.store.selectProtocolIdentifier() this.airGapTxs$ = this.store.selectAirGapTxs() this.aggregatedDetails$ = this.store.selectAggregatedDetails() @@ -26,7 +27,33 @@ export class TransactionComponent implements OnInit { public async ngOnInit(): Promise { if (this.airGapTxs !== undefined) { + await this.setAddressNames() this.store.setAirGapTxs(this.airGapTxs) } } + + public async ngOnChanges() { + await this.setAddressNames() + this.store.setAirGapTxs(this.airGapTxs) + } + + private async setAddressNames() { + const isBookenabled = await this.contactsService.isBookEnabled() + if (isBookenabled) { + for (let i = 0; i < this.airGapTxs.length; i++) { + this.airGapTxs[i].extra = { names: {} } + for (let j = 0; j < this.airGapTxs[i].from.length; j++) { + const address = this.airGapTxs[i].from[j] + const name = await this.contactsService.getContactName(address) + if (name) this.airGapTxs[i].extra.names[address] = name + } + + for (let j = 0; j < this.airGapTxs[i].to.length; j++) { + const address = this.airGapTxs[i].to[j] + const name = await this.contactsService.getContactName(address) + if (name) this.airGapTxs[i].extra.names[address] = name + } + } + } + } } diff --git a/src/app/pages/Installation-type/installation-type.page.html b/src/app/pages/Installation-type/installation-type.page.html index 0421038a..30f25acb 100644 --- a/src/app/pages/Installation-type/installation-type.page.html +++ b/src/app/pages/Installation-type/installation-type.page.html @@ -6,10 +6,19 @@ + + + + + + + + Select an installation type according to your preference +
  • High security
  • -
  • Same device option
  • -
  • Internet check disabled
  • +
  • Same device communication
  • @@ -75,7 +83,40 @@
    • Highest security
    • -
    • QR communication
    • +
    • QR communication
    • +
    + + + + + + + + + + + hybrid + + + + + + + + + + + + This is a device which at times may be connected to the internet +
      +
    • High security
    • +
    • + Same device and QR communication +
    diff --git a/src/app/pages/Installation-type/installation-type.page.ts b/src/app/pages/Installation-type/installation-type.page.ts index f80b39ec..6e9660be 100644 --- a/src/app/pages/Installation-type/installation-type.page.ts +++ b/src/app/pages/Installation-type/installation-type.page.ts @@ -3,6 +3,7 @@ import { ModalController } from '@ionic/angular' import { ErrorCategory, handleErrorLocal } from '../../services/error-handler/error-handler.service' import { InstallationType, VaultStorageKey, VaultStorageService } from '../../services/storage/storage.service' +import { OnboardingWelcomePage } from '../onboarding-welcome/onboarding-welcome.page' @Component({ selector: 'airgap-installation-type', @@ -14,6 +15,8 @@ export class InstallationTypePage { public installationTypes: typeof InstallationType = InstallationType + public isOnboardingFlow: boolean = false + /** * This will be true if the page is opened as a modal from the settings page. */ @@ -21,6 +24,7 @@ export class InstallationTypePage { constructor(private readonly modalController: ModalController, private readonly storageService: VaultStorageService) { this.storageService.get(VaultStorageKey.INSTALLATION_TYPE).then((installationType) => (this.installationType = installationType)) + this.storageService.get(VaultStorageKey.DISCLAIMER_HIDE_LOCAL_AUTH_ONBOARDING).then((value) => (this.isOnboardingFlow = !value)) } public close() { @@ -35,4 +39,13 @@ export class InstallationTypePage { }) .catch(handleErrorLocal(ErrorCategory.SECURE_STORAGE)) } + + public async goToOnboardingWelcomePage(): Promise { + const modal: HTMLIonModalElement = await this.modalController.create({ + component: OnboardingWelcomePage, + backdropDismiss: false + }) + + modal.present().catch(handleErrorLocal(ErrorCategory.IONIC_MODAL)) + } } diff --git a/src/app/pages/account-add/account-add.page.ts b/src/app/pages/account-add/account-add.page.ts index 601760cb..f14a98c3 100644 --- a/src/app/pages/account-add/account-add.page.ts +++ b/src/app/pages/account-add/account-add.page.ts @@ -61,6 +61,10 @@ export class AccountAddPage { ) { const state = this.navigationService.getState() this.secret = state.secret + } + + public ionViewWillEnter(): void { + const state = this.navigationService.getState() this.protocolService.getActiveProtocols().then(async (protocols: ICoinProtocol[]) => { const navigationIdentifier: ProtocolSymbols | undefined = state.protocol diff --git a/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.module.ts b/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.module.ts new file mode 100644 index 00000000..49c6cdd2 --- /dev/null +++ b/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.module.ts @@ -0,0 +1,22 @@ +import { ComponentsModule } from '@airgap/angular-core' +import { CommonModule } from '@angular/common' +import { NgModule } from '@angular/core' +import { FormsModule, ReactiveFormsModule } from '@angular/forms' +import { RouterModule, Routes } from '@angular/router' +import { IonicModule } from '@ionic/angular' +import { TranslateModule } from '@ngx-translate/core' + +import { ContactBookContactsDetailPage } from './contact-book-contacts-detail.page' + +const routes: Routes = [ + { + path: '', + component: ContactBookContactsDetailPage + } +] + +@NgModule({ + imports: [CommonModule, FormsModule, ReactiveFormsModule, IonicModule, RouterModule.forChild(routes), TranslateModule, ComponentsModule], + declarations: [ContactBookContactsDetailPage] +}) +export class ContactBookContactsDetailPageModule {} diff --git a/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.page.html b/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.page.html new file mode 100644 index 00000000..64e76c86 --- /dev/null +++ b/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.page.html @@ -0,0 +1,129 @@ + + + + + + +

    {{ 'contact-book.label_edit' | translate }}

    +
    +
    + + +

    {{ 'contact-book.label_cancel' | translate }}

    +
    + {{ "New Address Entry" }} + +

    {{ 'contact-book.label_finish' | translate }}

    +
    +
    + + +

    {{ 'contact-book.label_cancel' | translate }}

    +
    + +

    {{ 'contact-book.label_finish' | translate }}

    +
    +
    +
    + + +
    +
    + +
    + +

    {{contact?.name || ""}}

    +
    + {{ 'contact-book.label_added_by' | translate }} + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + {{ 'contact-book.label_name' | translate }} + + + + {{ 'contact-book.label_address' | translate }} + + + + {{ 'contact-book.label_creation_date' | translate }} + + + + + +
    +
    diff --git a/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.page.scss b/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.page.scss new file mode 100644 index 00000000..9d031726 --- /dev/null +++ b/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.page.scss @@ -0,0 +1,76 @@ +ion-content { + --padding-bottom: var(--ion-padding, 64px); +} + +ion-item { + margin-bottom: 12px; + border-radius: 6px; + overflow: hidden; +} + +ion-list { + width: 100%; +} + +ion-item { + opacity: 1; + color: black; + font-weight: 800; +} + +.top-button { + font-weight: 600; + margin: 0px 12px; + cursor: pointer; +} + +.input_disabled { + font-weight: 400; + color: rgba(128, 128, 128, 0.793); +} + +.input_enabled { + font-weight: 400; +} + +.main-wrapper { + display: flex; + flex-direction: column; + align-items: center; + + .image-wrapper { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 24px; + margin-top: 24px; + + .image { + width: 80px; + height: 80px; + background-color: pink; + border-radius: 100%; + } + } + + .name { + margin: 0px 0px 4px 0px; + } + + .added-wrapper { + font-size: 14px; + color: rgba(255, 255, 255, 0.666); + margin: 0px 0px 24px 0px; + } + + .delete-button { + width: 100%; + background-color: white; + font-size: 14px; + padding: 0px; + height: 38px; + color: red; + border-radius: 6px; + margin-top: 24px; + } +} diff --git a/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.page.spec.ts b/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.page.spec.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.page.ts b/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.page.ts new file mode 100644 index 00000000..7ba842a3 --- /dev/null +++ b/src/app/pages/contact-book-contacts-detail/contact-book-contacts-detail.page.ts @@ -0,0 +1,101 @@ +import { Component } from '@angular/core' +import { AddType, ContactsService, ContactType } from 'src/app/services/contacts/contacts.service' +import { ErrorCategory, handleErrorLocal } from 'src/app/services/error-handler/error-handler.service' +import { NavigationService } from 'src/app/services/navigation/navigation.service' + +@Component({ + selector: 'airgap-contact-book-contacts-detail', + templateUrl: './contact-book-contacts-detail.page.html', + styleUrls: ['./contact-book-contacts-detail.page.scss'] +}) +export class ContactBookContactsDetailPage { + public addEnum: typeof AddType = AddType + + public state: 'view' | 'new' | 'edit' = 'new' + public contact: ContactType | undefined + + constructor(private readonly navigationService: NavigationService, private readonly contactsService: ContactsService) {} + + ionViewWillEnter() { + const state = this.navigationService?.getState() + if (state.isNew) { + this.state = 'new' + this.contact = {} as ContactType + if (state.addType && state.addType === AddType.RECOMMENDED && state.address && state.address.length > 0) { + this.contact.address = state.address + this.contact.addedFrom = AddType.RECOMMENDED + } else if (state.addType && state.addType === AddType.SIGNING && state.address && state.address.length > 0) { + this.contact.address = state.address + this.contact.addedFrom = AddType.SIGNING + } else { + this.contact.addedFrom = AddType.MANUAL + } + } else if (state.isEdit) this.state = 'edit' + else if (state.contact) { + this.state = 'view' + this.contact = state.contact + } + } + + onClickBack() { + this.navigationService.route('/contact-book-contacts').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } + + onClickCancel() { + if (this.state === 'new') this.navigationService.route('/contact-book-contacts').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + else this.state = 'view' + } + + async onClickFinish() { + if (!this.contact) { + console.error('No contact!') + return + } + + if (!this.contact.name || this.contact.name?.length <= 0) { + console.error('No name!') + return + } + + if (!this.contact.address || this.contact.address?.length <= 0) { + console.error('No address!') + return + } + + if (this.state === 'new') { + await this.contactsService.createContact(this.contact.name, this.contact.address, this.contact.addedFrom) + if (this.contact.addedFrom === AddType.RECOMMENDED) this.contactsService.deleteSuggestion(this.contact.address) + if (this.contact.addedFrom === AddType.SIGNING) + this.navigationService + .routeWithState('/transaction-signed', { entao: true }) + .catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + else this.navigationService.route('/contact-book-contacts').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } else if (this.state === 'edit') { + await this.contactsService.updateContact(this.contact.id, this.contact.name, this.contact.address) + this.navigationService.route('/contact-book-contacts').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } else console.error('Invalid state on finish') + } + + onClickEdit() { + this.state = 'edit' + } + + async onClickDelete() { + await this.contactsService.deleteContact(this.contact.id) + this.navigationService.route('/contact-book-contacts').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } + + onChangeName(event: any) { + if (!this.contact) { + this.contact = {} as ContactType + } + this.contact.name = event.target.value + } + + onChangeAddress(event: any) { + if (!this.contact) { + this.contact = {} as ContactType + } + this.contact.address = event.target.value + } +} diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-item/contact-book-contacts-item.component.html b/src/app/pages/contact-book-contacts/contact-book-contacts-item/contact-book-contacts-item.component.html new file mode 100644 index 00000000..251bd8e8 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-item/contact-book-contacts-item.component.html @@ -0,0 +1,76 @@ +
    +
    + +
    +
    +

    {{ name }}

    +

    {{ address }}

    +
    +
    +

    {{ date }}

    + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-item/contact-book-contacts-item.component.scss b/src/app/pages/contact-book-contacts/contact-book-contacts-item/contact-book-contacts-item.component.scss new file mode 100644 index 00000000..65c4ba78 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-item/contact-book-contacts-item.component.scss @@ -0,0 +1,52 @@ +.contact-wrapper { + display: flex; + align-items: center; + gap: 12px; + cursor: pointer; + transition: all ease 0.2s; + padding: 6px 12px; + margin: -6px -12px; + border-radius: 6px; + + &:hover { + background-color: rgba(128, 128, 128, 0.222); + } + + .contact-image-wrapper { + height: 40px; + width: 40px; + + .contact-image { + border-radius: 100%; + } + } + + .contact-name-wrapper { + flex: 1; + .contact-name { + margin: 0px; + font-weight: 700; + } + + .contact-address { + margin: 0px; + max-width: 60vw; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + color: rgb(153, 153, 153); + } + } + + .contact-icon-wrapper { + display: flex; + flex-direction: column; + align-items: flex-end; + + .contact-date { + margin: 0px; + color: rgb(153, 153, 153); + margin-bottom: 4px; + } + } +} diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-item/contact-book-contacts-item.component.ts b/src/app/pages/contact-book-contacts/contact-book-contacts-item/contact-book-contacts-item.component.ts new file mode 100644 index 00000000..97ddae6e --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-item/contact-book-contacts-item.component.ts @@ -0,0 +1,31 @@ +import { Component, Input } from '@angular/core' +import { AddType } from 'src/app/services/contacts/contacts.service' + +export enum SortType { + NAME = 'NAME', + ADDRESS = 'ADDRESS', + DATE_INTERACTION = 'DATE_INTERACTION', + DATE_CREATION = 'DATE_CREATION', + ADDED_BY = 'ADDED_BY' +} + +@Component({ + selector: 'airgap-contact-book-contacts-item', + templateUrl: './contact-book-contacts-item.component.html', + styleUrls: ['./contact-book-contacts-item.component.scss'] +}) +export class ContactBookContactsItemComponent { + public addEnum: typeof AddType = AddType + + @Input() + public name: string + + @Input() + public address: string + + @Input() + public date: string + + @Input() + public addedFrom: AddType +} diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-item/tab-secret-popover.component.spec.ts b/src/app/pages/contact-book-contacts/contact-book-contacts-item/tab-secret-popover.component.spec.ts new file mode 100644 index 00000000..15f2f6a2 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-item/tab-secret-popover.component.spec.ts @@ -0,0 +1,24 @@ +// import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +// import { IonicModule } from '@ionic/angular'; + +// import { TabSecretPopoverComponent } from './tab-secret-popover.component'; + +// describe('TabSecretPopoverComponent', () => { +// let component: TabSecretPopoverComponent; +// let fixture: ComponentFixture; + +// beforeEach(waitForAsync(() => { +// TestBed.configureTestingModule({ +// declarations: [ TabSecretPopoverComponent ], +// imports: [IonicModule.forRoot()] +// }).compileComponents(); + +// fixture = TestBed.createComponent(TabSecretPopoverComponent); +// component = fixture.componentInstance; +// fixture.detectChanges(); +// })); + +// it('should create', () => { +// expect(component).toBeTruthy(); +// }); +// }); diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-popover/contact-book-contacts-popover.component.html b/src/app/pages/contact-book-contacts/contact-book-contacts-popover/contact-book-contacts-popover.component.html new file mode 100644 index 00000000..d07a3c48 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-popover/contact-book-contacts-popover.component.html @@ -0,0 +1,15 @@ + + + {{ 'contact-book.label_sort_by' | translate }} + + + + + + {{ sortType.label }} + + + + + + diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-popover/contact-book-contacts-popover.component.scss b/src/app/pages/contact-book-contacts/contact-book-contacts-popover/contact-book-contacts-popover.component.scss new file mode 100644 index 00000000..fa2f7c67 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-popover/contact-book-contacts-popover.component.scss @@ -0,0 +1,20 @@ +ion-list { + padding: 6px; +} + +ion-list-header { + padding: 6px; + height: 0px; + + ion-label { + font-size: 20px; + font-weight: 800; + } +} + +ion-item { + ion-label { + font-size: 12px; + font-weight: 800; + } +} diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-popover/contact-book-contacts-popover.component.ts b/src/app/pages/contact-book-contacts/contact-book-contacts-popover/contact-book-contacts-popover.component.ts new file mode 100644 index 00000000..ec309ea8 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-popover/contact-book-contacts-popover.component.ts @@ -0,0 +1,38 @@ +import { Component, OnInit } from '@angular/core' +import { NavigationService } from 'src/app/services/navigation/navigation.service' + +export enum SortType { + NAME = 'NAME', + ADDRESS = 'ADDRESS', + DATE_CREATION = 'DATE_CREATION', + ADDED_BY = 'ADDED_BY' +} + +@Component({ + selector: 'airgap-contact-book-contacts-popover', + templateUrl: './contact-book-contacts-popover.component.html', + styleUrls: ['./contact-book-contacts-popover.component.scss'] +}) +export class ContactBookContactsPopoverComponent implements OnInit { + private readonly onClickSort: Function + private readonly defaultSortType: SortType | undefined + + public sortTypes: { id: string; label: string }[] = [ + { id: SortType.NAME, label: 'Standard (Name)' }, + { id: SortType.ADDRESS, label: 'Address' }, + { id: SortType.DATE_CREATION, label: 'Creation Date' }, + { id: SortType.ADDED_BY, label: 'Added by' } + ] + public selectedSortType: SortType | undefined + + constructor(public navigationService: NavigationService) {} + ngOnInit(): void { + this.selectedSortType = this.defaultSortType + } + + public async changeSort(sortType: SortType): Promise { + if (this.onClickSort) { + this.onClickSort(sortType) + } + } +} diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-popover/tab-secret-popover.component.spec.ts b/src/app/pages/contact-book-contacts/contact-book-contacts-popover/tab-secret-popover.component.spec.ts new file mode 100644 index 00000000..15f2f6a2 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-popover/tab-secret-popover.component.spec.ts @@ -0,0 +1,24 @@ +// import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +// import { IonicModule } from '@ionic/angular'; + +// import { TabSecretPopoverComponent } from './tab-secret-popover.component'; + +// describe('TabSecretPopoverComponent', () => { +// let component: TabSecretPopoverComponent; +// let fixture: ComponentFixture; + +// beforeEach(waitForAsync(() => { +// TestBed.configureTestingModule({ +// declarations: [ TabSecretPopoverComponent ], +// imports: [IonicModule.forRoot()] +// }).compileComponents(); + +// fixture = TestBed.createComponent(TabSecretPopoverComponent); +// component = fixture.componentInstance; +// fixture.detectChanges(); +// })); + +// it('should create', () => { +// expect(component).toBeTruthy(); +// }); +// }); diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.html b/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.html new file mode 100644 index 00000000..3b4c41ac --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.html @@ -0,0 +1,11 @@ +
    +
    +
    +

    {{ address }}

    +
    +
    + {{ 'contact-book.label_add' | translate }} + + +
    +
    diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.scss b/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.scss new file mode 100644 index 00000000..74aa5cd7 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.scss @@ -0,0 +1,54 @@ +.suggestion-wrapper { + display: flex; + align-items: center; + gap: 12px; + border: 2px solid #80808094; + border-radius: 6px; + padding: 4px 8px; + + .suggestion-image-wrapper { + height: 40px; + width: 40px; + + .suggestion-image { + width: 100%; + height: 100%; + border-radius: 100%; + } + } + + .suggestion-name-wrapper { + flex: 1; + + .suggestion-address { + line-break: anywhere; + margin: 0px; + font-weight: 500; + color: grey; + } + } + + .suggestion-icon-wrapper { + display: flex; + flex-direction: column; + align-items: flex-end; + + .suggestion-date { + margin: 0px; + } + } + + .suggestion-actions { + display: flex; + .suggestion-button { + font-size: 12px; + } + + ion-icon { + font-size: 26px; + margin-top: auto; + margin-bottom: auto; + margin-left: 8px; + } + } +} diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.spec.ts b/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.spec.ts new file mode 100644 index 00000000..15f2f6a2 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.spec.ts @@ -0,0 +1,24 @@ +// import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +// import { IonicModule } from '@ionic/angular'; + +// import { TabSecretPopoverComponent } from './tab-secret-popover.component'; + +// describe('TabSecretPopoverComponent', () => { +// let component: TabSecretPopoverComponent; +// let fixture: ComponentFixture; + +// beforeEach(waitForAsync(() => { +// TestBed.configureTestingModule({ +// declarations: [ TabSecretPopoverComponent ], +// imports: [IonicModule.forRoot()] +// }).compileComponents(); + +// fixture = TestBed.createComponent(TabSecretPopoverComponent); +// component = fixture.componentInstance; +// fixture.detectChanges(); +// })); + +// it('should create', () => { +// expect(component).toBeTruthy(); +// }); +// }); diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.ts b/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.ts new file mode 100644 index 00000000..11c9b590 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts-suggestion/contact-book-contacts-suggestion.component.ts @@ -0,0 +1,37 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core' +import { AddType } from 'src/app/services/contacts/contacts.service' + +export enum SortType { + NAME = 'NAME', + ADDRESS = 'ADDRESS', + DATE_INTERACTION = 'DATE_INTERACTION', + DATE_CREATION = 'DATE_CREATION', + ADDED_BY = 'ADDED_BY' +} + +@Component({ + selector: 'airgap-contact-book-contacts-suggestion', + templateUrl: './contact-book-contacts-suggestion.component.html', + styleUrls: ['./contact-book-contacts-suggestion.component.scss'] +}) +export class ContactBookContactsSuggestionComponent { + public addEnum: typeof AddType = AddType + + @Input() + public name: string + + @Input() + public address: string + + @Output() onClickAdd = new EventEmitter() + + @Output() onClickClose = new EventEmitter() + + onClickAddHandler() { + this.onClickAdd.emit(); + } + + onClickCloseHandler() { + this.onClickClose.emit(); + } +} diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts.module.ts b/src/app/pages/contact-book-contacts/contact-book-contacts.module.ts new file mode 100644 index 00000000..34f58c96 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts.module.ts @@ -0,0 +1,31 @@ +import { ComponentsModule } from '@airgap/angular-core' +import { CommonModule } from '@angular/common' +import { NgModule } from '@angular/core' +import { FormsModule, ReactiveFormsModule } from '@angular/forms' +import { RouterModule, Routes } from '@angular/router' +import { IonicModule } from '@ionic/angular' +import { TranslateModule } from '@ngx-translate/core' +import { ContactBookContactsItemComponent } from './contact-book-contacts-item/contact-book-contacts-item.component' + +import { ContactBookContactsPopoverComponent } from './contact-book-contacts-popover/contact-book-contacts-popover.component' +import { ContactBookContactsSuggestionComponent } from './contact-book-contacts-suggestion/contact-book-contacts-suggestion.component' +import { ContactBookContactsPage } from './contact-book-contacts.page' + +const routes: Routes = [ + { + path: '', + component: ContactBookContactsPage + } +] + +@NgModule({ + entryComponents: [ContactBookContactsPopoverComponent, ContactBookContactsItemComponent, ContactBookContactsSuggestionComponent], + imports: [CommonModule, FormsModule, ReactiveFormsModule, IonicModule, RouterModule.forChild(routes), TranslateModule, ComponentsModule], + declarations: [ + ContactBookContactsPage, + ContactBookContactsPopoverComponent, + ContactBookContactsItemComponent, + ContactBookContactsSuggestionComponent + ] +}) +export class ContactBookContactsPageModule {} diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts.page.html b/src/app/pages/contact-book-contacts/contact-book-contacts.page.html new file mode 100644 index 00000000..f02352ef --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts.page.html @@ -0,0 +1,99 @@ + + + + + + {{ 'contact-book.title_address_book' | translate }} + + + + + + + + + + + + + + + + + + + + +
    +

    {{addedType}}

    +
    + +
    +
    +
    + + +
    +

    {{date}}

    +
    + +
    +
    +
    + + +
    +

    {{address}}

    +
    + +
    +
    +
    + + +
    +

    {{letter}}

    +
    + +
    +
    +
    + + +
    +

    {{ 'contact-book.label_suggestions' | translate }}

    +
    + +
    +
    +
    +
    +
    diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts.page.scss b/src/app/pages/contact-book-contacts/contact-book-contacts.page.scss new file mode 100644 index 00000000..bd802f08 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts.page.scss @@ -0,0 +1,35 @@ +ion-content { + --padding-bottom: var(--ion-padding, 64px); +} + +ion-toolbar { + --background: var(--ion-color-secondary); +} + +ion-toolbar { + --color: var(--ion-color-secondary-contrast); +} + +.contacts-wrapper { + display: flex; + flex-direction: column; + gap: 20px; + + .contacts-letter { + border-bottom: 1px solid black; + margin: 24px 0px 0px 0px; + } +} + +.suggestions-wrapper { + display: flex; + flex-direction: column; + gap: 6px; + margin-top: 12px; + + .suggestions-header { + font-size: 1rem; + margin-bottom: 0px; + font-weight: 800; + } +} diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts.page.spec.ts b/src/app/pages/contact-book-contacts/contact-book-contacts.page.spec.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/pages/contact-book-contacts/contact-book-contacts.page.ts b/src/app/pages/contact-book-contacts/contact-book-contacts.page.ts new file mode 100644 index 00000000..858efc71 --- /dev/null +++ b/src/app/pages/contact-book-contacts/contact-book-contacts.page.ts @@ -0,0 +1,166 @@ +import { Component, OnInit } from '@angular/core' +import { PopoverController } from '@ionic/angular' +import { AddType, ContactInfo, ContactsService } from 'src/app/services/contacts/contacts.service' +import { ErrorCategory, handleErrorLocal } from 'src/app/services/error-handler/error-handler.service' +import { NavigationService } from 'src/app/services/navigation/navigation.service' +import { ContactBookContactsPopoverComponent, SortType } from './contact-book-contacts-popover/contact-book-contacts-popover.component' + +enum SortDirection { + ASCENDING = 'ASCENDING', + DESCENDING = 'DESCENDING' +} + +@Component({ + selector: 'airgap-contact-book-contacts', + templateUrl: './contact-book-contacts.page.html', + styleUrls: ['./contact-book-contacts.page.scss'] +}) +export class ContactBookContactsPage implements OnInit { + public addEnum: typeof AddType = AddType + public sortEnum: typeof SortType = SortType + + public sortType: SortType = SortType.NAME + public sortDirection: SortDirection = SortDirection.DESCENDING + + public contacts: ContactInfo[] = [] + public suggestions: string[] = [] + + constructor( + private readonly popoverCtrl: PopoverController, + private readonly navigationService: NavigationService, + private readonly contactsService: ContactsService + ) {} + + async ngOnInit() { + this.contacts = await this.contactsService.getContactsInfo() + const suggestionsEnabled = await this.contactsService.isSuggestionsEnabled() + this.suggestions = suggestionsEnabled ? await this.contactsService.getSuggestions() : [] + } + + public async onClickBack() { + this.navigationService.route('/tabs/tab-settings').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } + + public async onSearch(event: any) { + const value = event.target.value.toLowerCase() + const storedContacts = await this.contactsService.getContactsInfo() + + const result = storedContacts.filter( + (contact) => contact.name.toLowerCase().includes(value) || contact.address.toLowerCase().includes(value) + ) + this.contacts = result + } + + public onClickNew(_: any) { + this.navigationService + .routeWithState('/contact-book-contacts-detail', { isNew: true }, { replaceUrl: true }) + .catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } + + public onClickItem(contact: ContactInfo) { + this.navigationService + .routeWithState('/contact-book-contacts-detail', { contact: contact }) + .catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } + + public async onClickSort(event: any) { + // TODO: error on second click + const popover = await this.popoverCtrl.create({ + component: ContactBookContactsPopoverComponent, + componentProps: { + defaultSortType: this.sortType, + onClickSort: (sortType: SortType): void => { + this.sortType = sortType + popover.dismiss().catch(handleErrorLocal(ErrorCategory.IONIC_MODAL)) + } + }, + event, + translucent: true + }) + + popover.present().catch(handleErrorLocal(ErrorCategory.IONIC_MODAL)) + } + + public async onClickAddSuggestion(address: string) { + this.navigationService + .routeWithState( + '/contact-book-contacts-detail', + { isNew: true, addType: AddType.RECOMMENDED, address: address }, + { replaceUrl: true } + ) + .catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } + + public async onClickCloseSuggestion(address: string) { + await this.contactsService.deleteSuggestion(address) + this.suggestions = await this.contactsService.getSuggestions() + } + + public getLettersFromNames(): string[] { + const letters: string[] = [] + for (let i = 0; i < this.contacts.length; i++) { + const name = this.contacts[i].name + const letter = name.charAt(0).toUpperCase() + if (!letters.includes(letter)) letters.push(letter) + } + return letters.sort() + } + + public getContactsFromLetter(letter: string): ContactInfo[] { + const contacts: ContactInfo[] = [] + for (let i = 0; i < this.contacts.length; i++) { + const name = this.contacts[i].name + const _letter = name.charAt(0).toUpperCase() + if (_letter === letter) contacts.push(this.contacts[i]) + } + return contacts + } + + public getAddressesFromContacts(): string[] { + const addresses: string[] = [] + for (let i = 0; i < this.contacts.length; i++) { + if (!addresses.includes(this.contacts[i].address)) addresses.push(this.contacts[i].address) + } + return addresses.sort() + } + + public getContactsFromAddress(address: string): ContactInfo[] { + const contacts: ContactInfo[] = [] + for (let i = 0; i < this.contacts.length; i++) { + if (address === this.contacts[i].address) contacts.push(this.contacts[i]) + } + return contacts + } + + public getDatesFromContacts(): string[] { + const dates: string[] = [] + for (let i = 0; i < this.contacts.length; i++) { + if (!dates.includes(this.contacts[i].date)) dates.push(this.contacts[i].date) + } + return dates.sort() + } + + public getContactsFromDate(date: string): ContactInfo[] { + const contacts: ContactInfo[] = [] + for (let i = 0; i < this.contacts.length; i++) { + if (date === this.contacts[i].date) contacts.push(this.contacts[i]) + } + return contacts + } + + public getAddedTypesFromContacts(): AddType[] { + const addTypes: AddType[] = [] + for (let i = 0; i < this.contacts.length; i++) { + if (!addTypes.includes(this.contacts[i].addedFrom)) addTypes.push(this.contacts[i].addedFrom) + } + return addTypes.sort() + } + + public getContactsFromAddedType(addedType: AddType): ContactInfo[] { + const contacts: ContactInfo[] = [] + for (let i = 0; i < this.contacts.length; i++) { + if (addedType === this.contacts[i].addedFrom) contacts.push(this.contacts[i]) + } + return contacts + } +} diff --git a/src/app/pages/contact-book-onboarding/contact-book-onboarding.module.ts b/src/app/pages/contact-book-onboarding/contact-book-onboarding.module.ts new file mode 100644 index 00000000..1c97fe8b --- /dev/null +++ b/src/app/pages/contact-book-onboarding/contact-book-onboarding.module.ts @@ -0,0 +1,21 @@ +import { CommonModule } from '@angular/common' +import { NgModule } from '@angular/core' +import { FormsModule, ReactiveFormsModule } from '@angular/forms' +import { RouterModule, Routes } from '@angular/router' +import { IonicModule } from '@ionic/angular' +import { TranslateModule } from '@ngx-translate/core' + +import { ContactBookOnboardingPage } from './contact-book-onboarding.page' + +const routes: Routes = [ + { + path: '', + component: ContactBookOnboardingPage + } +] + +@NgModule({ + imports: [CommonModule, FormsModule, ReactiveFormsModule, IonicModule, RouterModule.forChild(routes), TranslateModule], + declarations: [ContactBookOnboardingPage] +}) +export class ContactBookOnboardingPageModule {} diff --git a/src/app/pages/contact-book-onboarding/contact-book-onboarding.page.html b/src/app/pages/contact-book-onboarding/contact-book-onboarding.page.html new file mode 100644 index 00000000..2ce1f298 --- /dev/null +++ b/src/app/pages/contact-book-onboarding/contact-book-onboarding.page.html @@ -0,0 +1,170 @@ + + + + + + {{ 'contact-book.title_address_book' | translate }} + + + + + +
    + + + +

    {{ 'contact-book.title_address_book' | translate }}

    +

    {{ 'contact-book.label_welcome_personal_address_book' | translate }}

    +

    {{ 'contact-book.label_this_allows_to' | translate }}

    +
      +
    • {{ 'contact-book.label_indentify_addresses_you_interact' | translate }}
    • +
    • {{ 'contact-book.label_store_manage_entries' | translate }}
    • +
    +
    +
    + + +
    + + + +

    {{ 'contact-book.label_add_address_entries' | translate }}

    +

    {{ 'contact-book.label_several_ways' | translate }}

    +
      +
    • + + + + {{ 'contact-book.label_scan_qr' | translate }} +
    • +
    • + + + + {{ 'contact-book.label_manual_entry' | translate }} +
    • +
    • + + + + {{ 'contact-book.label_recommended_by_us' | translate }} +
    • +
    • + + + + {{ 'contact-book.label_while_signing' | translate }} +
    • +
    +
    +
    + + +
    + + + +

    {{ 'contact-book.label_recommendations' | translate }}

    +

    {{ 'contact-book.label_recommendation_on_who' | translate }}

    +
    +

    {{ 'contact-book.label_suggestions' | translate }}

    + +
    +

    {{ 'contact-book.label_note_disable' | translate }}

    +
    +
    + +
    + +
    + +
    +
    + + {{ 'social-recovery-setup.back_label' | translate }} + +
    +
    + + {{(state == 2 ? 'introduction.continue_label' : 'social-recovery-setup.next_label') | translate }} + +
    +
    +
    diff --git a/src/app/pages/contact-book-onboarding/contact-book-onboarding.page.scss b/src/app/pages/contact-book-onboarding/contact-book-onboarding.page.scss new file mode 100644 index 00000000..b76055eb --- /dev/null +++ b/src/app/pages/contact-book-onboarding/contact-book-onboarding.page.scss @@ -0,0 +1,115 @@ +ion-content { + --padding-bottom: var(--ion-padding, 64px); +} + +svg { + font-size: 6rem; +} + +h3 { + font-size: 1.4rem; + line-height: 1.5rem; + margin-bottom: 2.6rem; + text-align: center; + max-width: 400px; +} + +p { + margin: 0px; + max-width: 300px; + text-align: center; +} + +li { + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 4px; + + &::before { + content: '• '; + font-size: 2rem; + margin: 0px; + height: 26px; + display: flex; + align-items: center; + justify-content: center; + } + + svg { + font-size: 1.4rem; + } +} + +.suggestion-wrapper { + display: flex; + align-items: center; + justify-content: space-between; + border: 2px dashed var(--ion-color-primary); + padding: 12px; + border-radius: 6px; + margin: 24px 0px 12px 0px; + width: 100%; + max-width: 300px; + + p { + font-weight: 700; + } +} + +.note { + color: #ffffff7d; + text-align: start; +} + +.content-wrapper { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 80vh; +} + +.row-center { + display: flex; + align-items: center; + justify-content: center; + gap: 0.6rem; + + .row-button { + font-size: large; + font-weight: bold; + color: rgba(255, 255, 255, 0.8); + width: 12px; + height: 12px; + padding: 0px; + } + + ion-button { + --padding-start: 0px; + --padding-end: 0px; + } +} + +.buttons-wrapper { + display: flex; + align-items: center; + position: fixed; + bottom: 20px; + left: 0px; + width: 100%; + + .button-wrapper { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + + ion-button { + --padding-top: 24px; + --padding-bottom: 24px; + --padding-start: 48px; + --padding-end: 48px; + } + } +} diff --git a/src/app/pages/contact-book-onboarding/contact-book-onboarding.page.spec.ts b/src/app/pages/contact-book-onboarding/contact-book-onboarding.page.spec.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/pages/contact-book-onboarding/contact-book-onboarding.page.ts b/src/app/pages/contact-book-onboarding/contact-book-onboarding.page.ts new file mode 100644 index 00000000..497a3a4b --- /dev/null +++ b/src/app/pages/contact-book-onboarding/contact-book-onboarding.page.ts @@ -0,0 +1,44 @@ +import { Component, OnInit } from '@angular/core' +import { ContactsService } from 'src/app/services/contacts/contacts.service' +import { ErrorCategory, handleErrorLocal } from 'src/app/services/error-handler/error-handler.service' +import { NavigationService } from 'src/app/services/navigation/navigation.service' + +@Component({ + selector: 'airgap-contact-book-onboarding', + templateUrl: './contact-book-onboarding.page.html', + styleUrls: ['./contact-book-onboarding.page.scss'] +}) +export class ContactBookOnboardingPage implements OnInit { + public suggestionsEnabled: boolean + public state: 0 | 1 | 2 + + constructor(private readonly contactsService: ContactsService, private readonly navigationService: NavigationService) { + this.state = 0 + } + + async ngOnInit(): Promise { + this.contactsService.isSuggestionsEnabled().then((value: boolean) => (this.suggestionsEnabled = value)) + } + + changeState(state: 0 | 1 | 2) { + this.state = state + } + + async next() { + if (this.state < 2) this.state++ + else { + await this.contactsService.setOnboardingEnable(false) + await this.contactsService.setBookEnable(true) + this.navigationService.route('/contact-book-contacts').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } + } + + prev() { + if (this.state > 0) this.state-- + } + + async onToggleSuggestion(event: any) { + const value = event.detail.checked + await this.contactsService.setSuggestionsEnable(value) + } +} diff --git a/src/app/pages/contact-book-settings/contact-book-settings.module.ts b/src/app/pages/contact-book-settings/contact-book-settings.module.ts new file mode 100644 index 00000000..aaf3c1a6 --- /dev/null +++ b/src/app/pages/contact-book-settings/contact-book-settings.module.ts @@ -0,0 +1,21 @@ +import { CommonModule } from '@angular/common' +import { NgModule } from '@angular/core' +import { FormsModule, ReactiveFormsModule } from '@angular/forms' +import { RouterModule, Routes } from '@angular/router' +import { IonicModule } from '@ionic/angular' +import { TranslateModule } from '@ngx-translate/core' + +import { ContactBookSettingsPage } from './contact-book-settings.page' + +const routes: Routes = [ + { + path: '', + component: ContactBookSettingsPage + } +] + +@NgModule({ + imports: [CommonModule, FormsModule, ReactiveFormsModule, IonicModule, RouterModule.forChild(routes), TranslateModule], + declarations: [ContactBookSettingsPage] +}) +export class ContactBookOnboardingPageModule {} diff --git a/src/app/pages/contact-book-settings/contact-book-settings.page.html b/src/app/pages/contact-book-settings/contact-book-settings.page.html new file mode 100644 index 00000000..01dfdf70 --- /dev/null +++ b/src/app/pages/contact-book-settings/contact-book-settings.page.html @@ -0,0 +1,22 @@ + + + + + + {{ 'contact-book.title_settings' | translate }} + + + + + + + {{ 'contact-book.label_enable_address_book' | translate }} + + + + {{ 'contact-book.label_enable_suggestions' | translate }} + + + + + diff --git a/src/app/pages/contact-book-settings/contact-book-settings.page.scss b/src/app/pages/contact-book-settings/contact-book-settings.page.scss new file mode 100644 index 00000000..55de23cb --- /dev/null +++ b/src/app/pages/contact-book-settings/contact-book-settings.page.scss @@ -0,0 +1,23 @@ +ion-content { + --padding-bottom: var(--ion-padding, 64px); +} + +ion-toolbar { + --background: var(--ion-color-secondary); +} + +ion-toolbar { + --color: var(--ion-color-secondary-contrast); +} + +.delete-button { + width: calc(100% - 24px); + background-color: white; + font-size: 14px; + padding: 0px; + height: 38px; + color: red; + border-radius: 6px; + margin: 24px 12px 0px 12px; + border: 1px solid rgb(194, 194, 194); +} diff --git a/src/app/pages/contact-book-settings/contact-book-settings.page.spec.ts b/src/app/pages/contact-book-settings/contact-book-settings.page.spec.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/pages/contact-book-settings/contact-book-settings.page.ts b/src/app/pages/contact-book-settings/contact-book-settings.page.ts new file mode 100644 index 00000000..f44b2eff --- /dev/null +++ b/src/app/pages/contact-book-settings/contact-book-settings.page.ts @@ -0,0 +1,37 @@ +import { Component, OnInit } from '@angular/core' +import { ContactsService } from 'src/app/services/contacts/contacts.service' +import { ErrorCategory, handleErrorLocal } from 'src/app/services/error-handler/error-handler.service' +import { NavigationService } from 'src/app/services/navigation/navigation.service' + +@Component({ + selector: 'airgap-contact-book-settings', + templateUrl: './contact-book-settings.page.html', + styleUrls: ['./contact-book-settings.page.scss'] +}) +export class ContactBookSettingsPage implements OnInit { + public bookEnabled: boolean = true + public suggestionsEnabled: boolean + + constructor(private readonly navigationService: NavigationService, private readonly contactsService: ContactsService) {} + + async ngOnInit(): Promise { + this.contactsService.isBookEnabled().then((value: boolean) => (this.bookEnabled = value)) + this.contactsService.isSuggestionsEnabled().then((value: boolean) => (this.suggestionsEnabled = value)) + } + + public async toggleAddressBook(event: any) { + const value = event.detail.checked + await this.contactsService.setBookEnable(value) + } + + public async toggleEnableSuggestions(event: any) { + const value = event.detail.checked + await this.contactsService.setSuggestionsEnable(value) + } + + public async onClickDelete() { + await this.contactsService.deleteAllContacts() + await this.contactsService.setOnboardingEnable(true) + this.navigationService.route('/tabs/tab-settings').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } +} diff --git a/src/app/pages/danger-zone/danger-zone.page.html b/src/app/pages/danger-zone/danger-zone.page.html index 3f82990c..6bbe352b 100644 --- a/src/app/pages/danger-zone/danger-zone.page.html +++ b/src/app/pages/danger-zone/danger-zone.page.html @@ -15,5 +15,11 @@ {{ 'danger-zone.wipe_label' | translate }} + + +
    diff --git a/src/app/pages/danger-zone/danger-zone.page.ts b/src/app/pages/danger-zone/danger-zone.page.ts index 0b100d7b..2b06317b 100644 --- a/src/app/pages/danger-zone/danger-zone.page.ts +++ b/src/app/pages/danger-zone/danger-zone.page.ts @@ -1,6 +1,10 @@ -import { Component, OnInit } from '@angular/core' +// import { IsolatedModuleMetadata, IsolatedModulesService, UiEventService } from '@airgap/angular-core' +import { Component, /* Inject, */ OnInit } from '@angular/core' +// import { FilePickerPlugin, PickFilesResult } from '@capawesome/capacitor-file-picker' import { AlertController } from '@ionic/angular' import { TranslateService } from '@ngx-translate/core' +// import { FILE_PICKER_PLUGIN } from 'src/app/capacitor-plugins/injection-tokens' +// import { ErrorCategory, handleErrorLocal } from 'src/app/services/error-handler/error-handler.service' import { NavigationService } from 'src/app/services/navigation/navigation.service' import { SecureStorageService } from 'src/app/services/secure-storage/secure-storage.service' import { VaultStorageService } from 'src/app/services/storage/storage.service' @@ -17,11 +21,14 @@ export class DangerZonePage implements OnInit { public readonly storageService: VaultStorageService, private readonly secureStorage: SecureStorageService, private readonly navigationService: NavigationService + // private readonly isolatedModuleService: IsolatedModulesService, + // private readonly uiEventService: UiEventService, + // @Inject(FILE_PICKER_PLUGIN) private readonly filePicker: FilePickerPlugin ) {} ngOnInit() {} - async resetVault() { + public async resetVault() { const alert = await this.alertCtrl.create({ header: this.translateService.instant('danger-zone.wipe.alert.title'), message: this.translateService.instant('danger-zone.wipe.alert.message'), @@ -51,7 +58,7 @@ export class DangerZonePage implements OnInit { alert.present() } - async resetVaultError() { + public async resetVaultError() { const alert = await this.alertCtrl.create({ header: this.translateService.instant('danger-zone.wipe-error.alert.title'), message: this.translateService.instant('danger-zone.wipe-error.alert.message'), @@ -63,4 +70,34 @@ export class DangerZonePage implements OnInit { }) alert.present() } + + // disable module side-loading until it's production ready + // public async loadModule() { + // let loader: HTMLIonLoadingElement | undefined + + // try { + // const { files }: PickFilesResult = await this.filePicker.pickFiles({ + // multiple: false, + // readData: false + // }) + // const { name, path } = files[0] + // if (!path) { + // throw new Error(`Can't open the file.`) + // } + + // loader = await this.uiEventService.getTranslatedLoader({ + // message: 'Loading...' + // }) + // await loader.present().catch(handleErrorLocal(ErrorCategory.IONIC_LOADER)) + // const metadata: IsolatedModuleMetadata = await this.isolatedModuleService.readModuleMetadata(name, path) + + // this.navigationService.routeWithState('/module-preview', { metadata }).catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + // } catch (e) { + // console.error('Loading protocol module data failed', e) + // // TODO: show alert + // } finally { + // loader?.dismiss().catch(handleErrorLocal(ErrorCategory.IONIC_LOADER)) + // loader = undefined + // } + // } } diff --git a/src/app/pages/introduction/introduction.page.html b/src/app/pages/introduction/introduction.page.html index da3ad3c8..c56cd777 100644 --- a/src/app/pages/introduction/introduction.page.html +++ b/src/app/pages/introduction/introduction.page.html @@ -22,6 +22,6 @@ - {{ 'introduction.continue_label' | translate }} + {{ 'introduction.skip_label' | translate }} diff --git a/src/app/pages/module-preview/module-preview-routing.module.ts b/src/app/pages/module-preview/module-preview-routing.module.ts new file mode 100644 index 00000000..7f9aaede --- /dev/null +++ b/src/app/pages/module-preview/module-preview-routing.module.ts @@ -0,0 +1,17 @@ +import { NgModule } from '@angular/core' +import { Routes, RouterModule } from '@angular/router' + +import { ModulePreviewPage } from './module-preview.page' + +const routes: Routes = [ + { + path: '', + component: ModulePreviewPage + } +] + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class ModulePreviewPageRoutingModule {} diff --git a/src/app/pages/module-preview/module-preview.actions.ts b/src/app/pages/module-preview/module-preview.actions.ts new file mode 100644 index 00000000..26c88435 --- /dev/null +++ b/src/app/pages/module-preview/module-preview.actions.ts @@ -0,0 +1,25 @@ + +import { IsolatedModuleMetadata } from '@airgap/angular-core' +import { createAction, props } from '@ngrx/store' + +const featureName = 'Module Preview' + +/**************** View Lifecycle ****************/ + +export const viewInitialization = createAction(`[${featureName}] View Initialization`) + +/**************** Navigation Data ****************/ + +export const navigationDataLoading = createAction(`[${featureName}] Navigation Data Loading`) +export const navigationDataLoaded = createAction( + `[${featureName}] Navigation Data Loaded`, + props<{ metadata: IsolatedModuleMetadata }>() +) +export const invalidData = createAction(`[${featureName}] Invalid Navigation Data`) + +/**************** User Interaction ****************/ + +export const installModule = createAction(`[${featureName}] Install Module`, props<{ metadata: IsolatedModuleMetadata }>()) +export const moduleInstalling = createAction(`[${featureName}] Module Installing`) +export const moduleInstalled = createAction(`[${featureName}] Module Installed`) +export const moduleFailedToInstall = createAction(`[${featureName}] Module Failed to Install`) \ No newline at end of file diff --git a/src/app/pages/module-preview/module-preview.effects.ts b/src/app/pages/module-preview/module-preview.effects.ts new file mode 100644 index 00000000..d2bcdc56 --- /dev/null +++ b/src/app/pages/module-preview/module-preview.effects.ts @@ -0,0 +1,64 @@ +import { isIsolatedModuleMetadata, IsolatedModuleMetadata, IsolatedModulesService } from '@airgap/angular-core' +import { Injectable } from '@angular/core' +import { Actions, createEffect, ofType } from '@ngrx/effects' +import { Action } from '@ngrx/store' +import { concat, from, of } from 'rxjs' +import { first, switchMap, tap } from 'rxjs/operators' +import { ErrorCategory, handleErrorLocal } from 'src/app/services/error-handler/error-handler.service' +import { NavigationService } from 'src/app/services/navigation/navigation.service' + +import * as actions from './module-preview.actions' + +@Injectable() +export class ModulePreviewEffects { + public navigationData$ = createEffect(() => + this.actions$.pipe( + ofType(actions.viewInitialization), + switchMap(() => concat(of(actions.navigationDataLoading()), from(this.loadNavigationData()).pipe(first()))) + ) + ) + + public installModule$ = createEffect(() => + this.actions$.pipe( + ofType(actions.installModule), + switchMap(({ metadata }) => concat(of(actions.moduleInstalling()), from(this.installModule(metadata)).pipe(first()))) + ) + ) + + public moduleInstalled$ = createEffect( + () => + this.actions$.pipe( + ofType(actions.moduleInstalled), + tap(() => this.navigateToHome()) + ), + { dispatch: false } + ) + + constructor( + private readonly actions$: Actions, + private readonly navigationService: NavigationService, + private readonly isolatedModuleService: IsolatedModulesService + ) {} + + private async loadNavigationData(): Promise { + const state = this.navigationService.getState() + + return isIsolatedModuleMetadata(state.metadata) + ? actions.navigationDataLoaded({ metadata: state.metadata }) + : actions.invalidData() + } + + private async installModule(metadata: IsolatedModuleMetadata): Promise { + try { + await this.isolatedModuleService.installModule(metadata) + return actions.moduleInstalled() + } catch (error) { + console.error(error) + return actions.moduleFailedToInstall() + } + } + + private async navigateToHome(): Promise { + this.navigationService.route('/').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } +} \ No newline at end of file diff --git a/src/app/pages/module-preview/module-preview.module.ts b/src/app/pages/module-preview/module-preview.module.ts new file mode 100644 index 00000000..3889f9ab --- /dev/null +++ b/src/app/pages/module-preview/module-preview.module.ts @@ -0,0 +1,31 @@ +import { NgModule } from '@angular/core' +import { CommonModule } from '@angular/common' +import { FormsModule } from '@angular/forms' + +import { IonicModule } from '@ionic/angular' + +import { ModulePreviewPageRoutingModule } from './module-preview-routing.module' + +import { ModulePreviewPage } from './module-preview.page' +import { TranslateModule } from '@ngx-translate/core' +import { StoreModule } from '@ngrx/store' + +import * as fromModulePreview from './module-preview.reducer' +import { EffectsModule } from '@ngrx/effects' +import { ModulePreviewEffects } from './module-preview.effects' +import { AirGapAngularCoreModule } from '@airgap/angular-core' + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + ModulePreviewPageRoutingModule, + TranslateModule, + StoreModule.forFeature('modulePreview', fromModulePreview.reducer), + EffectsModule.forFeature([ModulePreviewEffects]), + AirGapAngularCoreModule + ], + declarations: [ModulePreviewPage] +}) +export class ModulePreviewPageModule {} diff --git a/src/app/pages/module-preview/module-preview.page.html b/src/app/pages/module-preview/module-preview.page.html new file mode 100644 index 00000000..903c8fb6 --- /dev/null +++ b/src/app/pages/module-preview/module-preview.page.html @@ -0,0 +1,60 @@ + + + + + + + {{ 'module-preview.title' | translate: { name: moduleName } }} + + + + + + + + + + + + + + + + + + + + + + + + {{ 'module-preview.manifest.include.description' | translate }} + + + + {{ file }} + + + + + + + + + {{ 'module-preview.install-button_label' | translate }} + + + + diff --git a/src/app/pages/module-preview/module-preview.page.scss b/src/app/pages/module-preview/module-preview.page.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/pages/module-preview/module-preview.page.spec.ts b/src/app/pages/module-preview/module-preview.page.spec.ts new file mode 100644 index 00000000..4b4a5a05 --- /dev/null +++ b/src/app/pages/module-preview/module-preview.page.spec.ts @@ -0,0 +1,26 @@ +// import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing' +// import { IonicModule } from '@ionic/angular' + +// import { ModulePreviewPage } from './module-preview.page' + +// describe('ModulePreviewPage', () => { +// let component: ModulePreviewPage +// let fixture: ComponentFixture + +// beforeEach( +// waitForAsync(() => { +// TestBed.configureTestingModule({ +// declarations: [ModulePreviewPage], +// imports: [IonicModule.forRoot()] +// }).compileComponents() + +// fixture = TestBed.createComponent(ModulePreviewPage) +// component = fixture.componentInstance +// fixture.detectChanges() +// }) +// ) + +// it('should create', () => { +// expect(component).toBeTruthy() +// }) +// }) diff --git a/src/app/pages/module-preview/module-preview.page.ts b/src/app/pages/module-preview/module-preview.page.ts new file mode 100644 index 00000000..ad98ae4e --- /dev/null +++ b/src/app/pages/module-preview/module-preview.page.ts @@ -0,0 +1,41 @@ +import { isIsolatedModuleMetadata, IsolatedModuleMetadata, UIResource, UIResourceStatus } from '@airgap/angular-core' +import { Component, OnInit } from '@angular/core' +import { Store } from '@ngrx/store' +import { Observable } from 'rxjs' +import { NavigationService } from 'src/app/services/navigation/navigation.service' + +import * as actions from './module-preview.actions' +import * as fromModulePreview from './module-preview.reducer' + +@Component({ + selector: 'airgap-module-preview', + templateUrl: './module-preview.page.html', + styleUrls: ['./module-preview.page.scss'] +}) +export class ModulePreviewPage implements OnInit { + public readonly moduleName: string | undefined + + public readonly moduleMetadata$: Observable> + + public readonly UIResourceStatus: typeof UIResourceStatus = UIResourceStatus + + constructor( + private readonly store: Store, + private readonly navigationService: NavigationService + ) { + const state = this.navigationService.getState() + if (state.metadata && isIsolatedModuleMetadata(state.metadata)) { + this.moduleName = state.metadata.manifest.name + } + + this.moduleMetadata$ = this.store.select(fromModulePreview.selectModuleMetadata) + } + + public ngOnInit() { + this.store.dispatch(actions.viewInitialization()) + } + + public install(metadata: IsolatedModuleMetadata) { + this.store.dispatch(actions.installModule({ metadata })) + } +} diff --git a/src/app/pages/module-preview/module-preview.reducer.ts b/src/app/pages/module-preview/module-preview.reducer.ts new file mode 100644 index 00000000..45c29f0e --- /dev/null +++ b/src/app/pages/module-preview/module-preview.reducer.ts @@ -0,0 +1,56 @@ +import { IsolatedModuleMetadata, UIResource, UIResourceStatus } from '@airgap/angular-core' +import { createFeatureSelector, createReducer, createSelector, on } from '@ngrx/store' + +import * as fromRoot from '../../app.reducers' + +import * as actions from './module-preview.actions' + +/**************** State ****************/ + +export interface FeatureState { + moduleMetadata: UIResource +} + +export interface State extends fromRoot.State { + modulePreview: FeatureState +} + +/**************** Reducers ****************/ + +const initialState: FeatureState = { + moduleMetadata: { + value: undefined, + status: UIResourceStatus.IDLE + } +} + +export const reducer = createReducer( + initialState, + on(actions.navigationDataLoading, (state) => ({ + ...state, + moduleMetadata: { + value: state.moduleMetadata.value, + status: UIResourceStatus.LOADING + } + })), + on(actions.navigationDataLoaded, (state, { metadata }) => ({ + ...state, + moduleMetadata: { + value: metadata, + status: UIResourceStatus.SUCCESS + } + })), + on(actions.invalidData, (state) => ({ + ...state, + moduleMetadata: { + value: state.moduleMetadata.value, + status: UIResourceStatus.ERROR + } + })) +) + +/**************** Selectors ****************/ + +export const selectFeatureState = createFeatureSelector('modulePreview') + +export const selectModuleMetadata = createSelector(selectFeatureState, (state: FeatureState): FeatureState['moduleMetadata'] => state.moduleMetadata) \ No newline at end of file diff --git a/src/app/pages/module-preview/module-preview.types.ts b/src/app/pages/module-preview/module-preview.types.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/app/pages/onboarding-advanced-mode/onboarding-advanced-mode.page.html b/src/app/pages/onboarding-advanced-mode/onboarding-advanced-mode.page.html index 74bb58ee..8a9f6168 100644 --- a/src/app/pages/onboarding-advanced-mode/onboarding-advanced-mode.page.html +++ b/src/app/pages/onboarding-advanced-mode/onboarding-advanced-mode.page.html @@ -54,7 +54,6 @@
    • BIP39 Passphrases
    • Lifehash Identicons
    • -
    • Dice and Coin-Flip Entropy Collection
    diff --git a/src/app/pages/secret-rules/secret-rules.page.html b/src/app/pages/secret-rules/secret-rules.page.html index 742a474a..9a45edad 100644 --- a/src/app/pages/secret-rules/secret-rules.page.html +++ b/src/app/pages/secret-rules/secret-rules.page.html @@ -15,6 +15,8 @@

    {{ 'secret-rules.heading' | translate }}

    {{ 'secret-rules.description' | translate }}

    +

    {{ 'secret-rules.confirm' | translate }}

    + {{ 'secret-rules.rules-list.item-1_text' | translate }} diff --git a/src/app/pages/secret-setup/secret-setup.page.html b/src/app/pages/secret-setup/secret-setup.page.html index e7c3bce0..38a9c251 100644 --- a/src/app/pages/secret-setup/secret-setup.page.html +++ b/src/app/pages/secret-setup/secret-setup.page.html @@ -1,7 +1,10 @@ - + - + + + + {{ 'secret-setup.heading' | translate }} @@ -50,12 +53,27 @@ - - {{ 'wallet-select-coins.advanced_label' | translate }} + + {{ 'secret-setup.advanced' | translate }} + + +

    + {{ 'secret-setup.advanced' | translate }} +

    + +

    +
    +
    + + + {{ 'secret-setup.advanced' | translate }} + + + diff --git a/src/app/pages/secret-setup/secret-setup.page.ts b/src/app/pages/secret-setup/secret-setup.page.ts index fe29be28..d315de46 100644 --- a/src/app/pages/secret-setup/secret-setup.page.ts +++ b/src/app/pages/secret-setup/secret-setup.page.ts @@ -1,4 +1,5 @@ import { Component, OnInit } from '@angular/core' +import { ModalController } from '@ionic/angular' import { first } from 'rxjs/operators' import { MnemonicSecret } from '../../models/secret' @@ -7,6 +8,7 @@ import { ErrorCategory, handleErrorLocal } from '../../services/error-handler/er import { NavigationService } from '../../services/navigation/navigation.service' import { SecretsService } from '../../services/secrets/secrets.service' import { VaultStorageKey, VaultStorageService } from '../../services/storage/storage.service' +import { InstallationTypePage } from '../Installation-type/installation-type.page' @Component({ selector: 'airgap-secret-setup', @@ -21,6 +23,7 @@ export class SecretSetupPage implements OnInit { constructor( private readonly navigationService: NavigationService, private readonly secretsService: SecretsService, + private readonly modalController: ModalController, private readonly deviceService: DeviceService, private readonly storageService: VaultStorageService ) {} @@ -68,4 +71,13 @@ export class SecretSetupPage implements OnInit { public goToCoinFlipPage(): void { this.navigationService.route('/secret-generate-coin-flip').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) } + + public async goToInstallationTypePage(): Promise { + const modal: HTMLIonModalElement = await this.modalController.create({ + component: InstallationTypePage, + backdropDismiss: false + }) + + modal.present().catch(handleErrorLocal(ErrorCategory.IONIC_MODAL)) + } } diff --git a/src/app/pages/tab-settings/tab-settings.page.html b/src/app/pages/tab-settings/tab-settings.page.html index 87ebf674..64158c68 100644 --- a/src/app/pages/tab-settings/tab-settings.page.html +++ b/src/app/pages/tab-settings/tab-settings.page.html @@ -89,4 +89,20 @@ {{ 'tab-settings.danger-zone_label' | translate }}
    + + + + {{ 'tab-settings.advanced-features_label' | translate }} + + + + + {{ 'tab-settings.address_book_label' | translate }} + + + + + {{ 'tab-settings.configure_address_book_label' | translate }} + + diff --git a/src/app/pages/tab-settings/tab-settings.page.ts b/src/app/pages/tab-settings/tab-settings.page.ts index bcb89829..d466553b 100644 --- a/src/app/pages/tab-settings/tab-settings.page.ts +++ b/src/app/pages/tab-settings/tab-settings.page.ts @@ -11,6 +11,7 @@ import { IACService } from 'src/app/services/iac/iac.service' import { InstallationTypePage } from '../Installation-type/installation-type.page' import { OnboardingAdvancedModePage } from '../onboarding-advanced-mode/onboarding-advanced-mode.page' import { OnboardingWelcomePage } from '../onboarding-welcome/onboarding-welcome.page' +import { ContactsService } from 'src/app/services/contacts/contacts.service' @Component({ selector: 'airgap-tab-settings', @@ -26,7 +27,8 @@ export class TabSettingsPage { private readonly modalController: ModalController, private readonly iacService: IACService, private readonly clipboardService: ClipboardService, - private readonly navigationService: NavigationService + private readonly navigationService: NavigationService, + private readonly contactsService: ContactsService ) { this.secrets = this.secretsService.getSecretsObservable() } @@ -55,6 +57,18 @@ export class TabSettingsPage { this.navigationService.route('/qr-settings').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) } + public async goToAddressBook(): Promise { + if (await this.contactsService.isOnboardingEnabled()) + this.navigationService.route('/contact-book-onboarding').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + else this.navigationService.route('/contact-book-contacts').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } + + public async goToAddressBookSettings(): Promise { + if (await this.contactsService.isOnboardingEnabled()) + this.navigationService.route('/contact-book-onboarding').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + else this.navigationService.route('/contact-book-settings').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) + } + public async goToOnboarding(): Promise { const modal: HTMLIonModalElement = await this.modalController.create({ component: OnboardingWelcomePage, diff --git a/src/app/pages/transaction-signed/transaction-signed.page.ts b/src/app/pages/transaction-signed/transaction-signed.page.ts index 8757cd19..def5da07 100644 --- a/src/app/pages/transaction-signed/transaction-signed.page.ts +++ b/src/app/pages/transaction-signed/transaction-signed.page.ts @@ -1,10 +1,11 @@ -import { Component } from '@angular/core' +import { Component, ViewChild } from '@angular/core' import { AirGapWallet } from '@airgap/coinlib-core' import { MessageSignResponse } from '@airgap/serializer' import { TranslateService } from '@ngx-translate/core' import { ErrorCategory, handleErrorLocal } from '../../services/error-handler/error-handler.service' import { NavigationService } from '../../services/navigation/navigation.service' +import { SignedTransactionComponent } from 'src/app/components/signed-transaction/signed-transaction.component' enum TransactionQRType { SignedAirGap = 0, @@ -17,6 +18,9 @@ enum TransactionQRType { styleUrls: ['./transaction-signed.page.scss'] }) export class TransactionSignedPage { + @ViewChild(SignedTransactionComponent) + private transactionComponent: SignedTransactionComponent + public signedTxs: string[] public interactionUrl: string @@ -32,6 +36,8 @@ export class TransactionSignedPage { public signedTransactionSync: any // TODO: Types + public addressesNotOnContactBook: string[] = [] + constructor(public navigationService: NavigationService, private readonly translateService: TranslateService) { this.interactionUrl = this.navigationService.getState().interactionUrl this.wallets = this.navigationService.getState().wallets @@ -42,6 +48,13 @@ export class TransactionSignedPage { this.messageSignResponse = this.navigationService.getState().messageSignResponse } + ionViewWillEnter() { + const temp = this.interactionUrl + this.interactionUrl = null + this.interactionUrl = temp + this.transactionComponent?.checkAdressesNames() + } + public done(): void { this.navigationService.routeToSecretsTab().catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION)) } diff --git a/src/app/services/contacts/contacts.service.spec.ts b/src/app/services/contacts/contacts.service.spec.ts new file mode 100644 index 00000000..f5956896 --- /dev/null +++ b/src/app/services/contacts/contacts.service.spec.ts @@ -0,0 +1,52 @@ +// import { ISOLATED_MODULES_PLUGIN, WebIsolatedModules } from '@airgap/angular-core' +// import { TestBed } from '@angular/core/testing' +// import { StorageMock } from 'test-config/storage-mock' + +// import { SecureStorageService } from '../secure-storage/secure-storage.service' +// import { VaultStorageService } from '../storage/storage.service' + +// import { UnitHelper } from '../../../../test-config/unit-test-helper' +// import { SecureStorageServiceMock } from '../secure-storage/secure-storage.mock' +// import { SecretsService } from './contacts.service' + +// describe('SecretsService', () => { +// // let storageService: StorageMock +// // let secureStorageService: SecureStorageServiceMock +// // let secretsService: SecretsService +// let unitHelper: UnitHelper +// beforeEach(() => { +// unitHelper = new UnitHelper() +// TestBed.configureTestingModule( +// unitHelper.testBed({ +// providers: [ +// SecretsService, +// { provide: VaultStorageService, useClass: StorageMock }, +// { provide: SecureStorageService, useClass: SecureStorageServiceMock }, +// { provide: ISOLATED_MODULES_PLUGIN, useValue: new WebIsolatedModules() } +// ] +// }) +// ) +// .compileComponents() +// .catch(console.error) +// }) + +// // beforeEach(() => { +// // secureStorageService = TestBed.get(SecureStorageServiceMock) +// // storageService = TestBed.get(Storage) +// // secretsService = TestBed.get(SecretsService) +// // }) + +// it('should be created', () => { +// const secretsService: SecretsService = TestBed.get(SecretsService) +// expect(secretsService).toBeTruthy() +// }) + +// it('should save a newly added secret to the local storage', async () => { +// // const storageStateBefore = await storage.get('airgap-secret-list') +// // expect(storageStateBefore).toBe(undefined) +// // const secret = new Secret('topSecret') +// // await secretsService.addOrUpdateSecret(secret) +// // const storageStateAfter = await storage.get('airgap-secret-list') +// // expect(storageStateAfter.length).toBe(1) +// }) +// }) diff --git a/src/app/services/contacts/contacts.service.ts b/src/app/services/contacts/contacts.service.ts new file mode 100644 index 00000000..cf30d1ad --- /dev/null +++ b/src/app/services/contacts/contacts.service.ts @@ -0,0 +1,155 @@ +import { Injectable } from '@angular/core' +import { VaultStorageKey, VaultStorageService } from '../storage/storage.service' + +export enum AddType { + QR = 'QR', + MANUAL = 'MANUAL', + RECOMMENDED = 'RECOMMENDED', + SIGNING = 'SIGNING' +} + +export interface ContactInfo { + id: string + name: string + address: string + date: string + addedFrom: AddType +} + +export interface ContactType { + id: string + name: string + address: string + date: string + addedFrom: AddType + transactions: string[] +} + +@Injectable({ + providedIn: 'root' +}) +export class ContactsService { + constructor(private readonly storageService: VaultStorageService) {} + + async getSuggestions(): Promise { + return (await this.storageService.get(VaultStorageKey.AIRGAP_CONTACTS_RECOMMENDED_LIST)) as string[] + } + + async addSuggestion(address: string): Promise { + const storedRecommendations: string[] = (await this.storageService.get(VaultStorageKey.AIRGAP_CONTACTS_RECOMMENDED_LIST)) as string[] + + const index = storedRecommendations.findIndex((suggestion) => suggestion === address) + if (index < 0) { + storedRecommendations.push(address) + await this.storageService.set(VaultStorageKey.AIRGAP_CONTACTS_RECOMMENDED_LIST, storedRecommendations) + } else console.error('Suggestion already stored') + } + + async deleteSuggestion(address: string): Promise { + const storedRecommendations: string[] = (await this.storageService.get(VaultStorageKey.AIRGAP_CONTACTS_RECOMMENDED_LIST)) as string[] + + const index = storedRecommendations.findIndex((suggestion) => suggestion === address) + if (index >= 0) { + storedRecommendations.splice(index, 1) + await this.storageService.set(VaultStorageKey.AIRGAP_CONTACTS_RECOMMENDED_LIST, storedRecommendations) + } else console.error('Invalid suggestion') + } + + async getContactsInfo(): Promise { + const storedContacts: ContactType[] = (await this.storageService.get(VaultStorageKey.AIRGAP_CONTACTS_LIST)) as ContactType[] + return storedContacts + } + + async createContact(name: string, address: string, addedFrom: AddType): Promise { + const storedContacts: ContactType[] = (await this.storageService.get(VaultStorageKey.AIRGAP_CONTACTS_LIST)) as ContactType[] + const storedRecommendations: string[] = (await this.storageService.get(VaultStorageKey.AIRGAP_CONTACTS_RECOMMENDED_LIST)) as string[] + + storedContacts.push({ + id: `contact${storedContacts.length + 1}`, + date: `${new Date().getDate()}. ${new Date().toLocaleString('default', { month: 'short' })}`, + name, + address, + addedFrom, + transactions: [] + }) + + const index = storedRecommendations.findIndex((recommendation) => recommendation === address) + if (index >= 0) { + storedRecommendations.splice(index, 1) + await this.storageService.set(VaultStorageKey.AIRGAP_CONTACTS_RECOMMENDED_LIST, storedRecommendations) + } + await this.storageService.set(VaultStorageKey.AIRGAP_CONTACTS_LIST, storedContacts) + } + + async updateContact(id: string, name: string, address: string): Promise { + const storedContacts: ContactType[] = (await this.storageService.get(VaultStorageKey.AIRGAP_CONTACTS_LIST)) as ContactType[] + + const index = storedContacts.findIndex((contact) => contact.id === id) + if (index < 0) { + console.error('No contact with id', id) + return + } + const contact = storedContacts[index] + contact.name = name + contact.address = address + + await this.storageService.set(VaultStorageKey.AIRGAP_CONTACTS_LIST, storedContacts) + } + + async deleteContact(id: string): Promise { + const storedContacts: ContactType[] = (await this.storageService.get(VaultStorageKey.AIRGAP_CONTACTS_LIST)) as ContactType[] + + const index = storedContacts.findIndex((contact) => contact.id === id) + if (index < 0) { + console.error('No contact with id', id) + return + } + storedContacts.splice(index, 1) + await this.storageService.set(VaultStorageKey.AIRGAP_CONTACTS_LIST, storedContacts) + } + + async deleteAllContacts(): Promise { + await this.storageService.set(VaultStorageKey.AIRGAP_CONTACTS_LIST, []) + } + + async isBookEnabled(): Promise { + return !(await this.storageService.get(VaultStorageKey.ADDRESS_BOOK_DISABLED)) + } + + async setBookEnable(value: boolean) { + await this.storageService.set(VaultStorageKey.ADDRESS_BOOK_DISABLED, !value) + } + + async isSuggestionsEnabled(): Promise { + return !(await this.storageService.get(VaultStorageKey.ADDRESS_BOOK_SUGGESTIONS_DISABLED)) + } + + async setSuggestionsEnable(value: boolean) { + await this.storageService.set(VaultStorageKey.ADDRESS_BOOK_SUGGESTIONS_DISABLED, !value) + } + + async isOnboardingEnabled(): Promise { + return !(await this.storageService.get(VaultStorageKey.ADDRESS_BOOK_ONBOARDING_DISABLED)) + } + + async setOnboardingEnable(value: boolean) { + await this.storageService.set(VaultStorageKey.ADDRESS_BOOK_ONBOARDING_DISABLED, !value) + } + + async isAddressInContacts(address: string): Promise { + const storedContacts: ContactType[] = (await this.storageService.get(VaultStorageKey.AIRGAP_CONTACTS_LIST)) as ContactType[] + const storedRecommendations: string[] = (await this.storageService.get(VaultStorageKey.AIRGAP_CONTACTS_RECOMMENDED_LIST)) as string[] + + const contactFound = storedContacts.find((contact) => contact.address === address) + const recommendationFound = storedRecommendations.find((recommendation) => recommendation === address) + + return !!contactFound && !recommendationFound + } + + async getContactName(address: string): Promise { + const storedContacts: ContactType[] = (await this.storageService.get(VaultStorageKey.AIRGAP_CONTACTS_LIST)) as ContactType[] + const contact = storedContacts.find((contact) => contact.address == address) + if (contact) return contact.name + else return undefined + } +} diff --git a/src/app/services/iac/iac.service.spec.ts b/src/app/services/iac/iac.service.spec.ts index f1bc699e..ecc11e33 100644 --- a/src/app/services/iac/iac.service.spec.ts +++ b/src/app/services/iac/iac.service.spec.ts @@ -3,7 +3,7 @@ import { TestBed } from '@angular/core/testing' import { IACService } from './iac.service' import { UnitHelper } from '../../../../test-config/unit-test-helper' -import { STATUS_BAR_PLUGIN, SPLASH_SCREEN_PLUGIN, APP_PLUGIN, CLIPBOARD_PLUGIN } from '@airgap/angular-core' +import { STATUS_BAR_PLUGIN, SPLASH_SCREEN_PLUGIN, APP_PLUGIN, CLIPBOARD_PLUGIN, ISOLATED_MODULES_PLUGIN, WebIsolatedModules } from '@airgap/angular-core' import { ModalController, NavController, NavParams, Platform } from '@ionic/angular' import { ClipboardMock, @@ -43,7 +43,8 @@ describe('IACService', () => { { provide: STATUS_BAR_PLUGIN, useClass: StatusBarMock }, { provide: SPLASH_SCREEN_PLUGIN, useClass: SplashScreenMock }, { provide: CLIPBOARD_PLUGIN, useClass: ClipboardMock }, - { provide: Platform, useClass: PlatformMock } + { provide: Platform, useClass: PlatformMock }, + { provide: ISOLATED_MODULES_PLUGIN, useValue: new WebIsolatedModules() } ] }) ) diff --git a/src/app/services/mode/mode.service.spec.ts b/src/app/services/mode/mode.service.spec.ts index 62c8c35a..d27fe4ad 100644 --- a/src/app/services/mode/mode.service.spec.ts +++ b/src/app/services/mode/mode.service.spec.ts @@ -1,4 +1,4 @@ -import { APP_PLUGIN, DeeplinkService } from '@airgap/angular-core' +import { APP_PLUGIN, DeeplinkService, ISOLATED_MODULES_PLUGIN, WebIsolatedModules } from '@airgap/angular-core' import { TestBed } from '@angular/core/testing' import { createAppSpy } from '../../../../test-config/plugins-mocks' @@ -29,7 +29,8 @@ describe('ModeService', () => { DeeplinkService, { provide: APP_PLUGIN, useValue: appSpy }, { provide: VaultStorageService, useClass: StorageMock }, - { provide: SecureStorageService, useClass: SecureStorageServiceMock } + { provide: SecureStorageService, useClass: SecureStorageServiceMock }, + { provide: ISOLATED_MODULES_PLUGIN, useValue: new WebIsolatedModules() } ] }) ) diff --git a/src/app/services/protocol-module/protocol-module.service.ts b/src/app/services/protocol-module/protocol-module.service.ts deleted file mode 100644 index 793984d1..00000000 --- a/src/app/services/protocol-module/protocol-module.service.ts +++ /dev/null @@ -1,190 +0,0 @@ -import { flattened, ICoinProtocolAdapter, ICoinSubProtocolAdapter } from '@airgap/angular-core' -import { AeternityModule } from '@airgap/aeternity/v1' -import { AstarModule } from '@airgap/astar/v1' -import { BitcoinModule } from '@airgap/bitcoin/v1' -import { ICoinProtocol, ICoinSubProtocol, ProtocolSymbols } from '@airgap/coinlib-core' -import { CosmosModule } from '@airgap/cosmos/v1' -import { EthereumModule } from '@airgap/ethereum/v1' -import { GroestlcoinModule } from '@airgap/groestlcoin/v1' -import { - AirGapBlockExplorer, - AirGapModule, - AirGapOfflineProtocol, - AirGapV3SerializerCompanion, - isSubProtocol, - ProtocolConfiguration, - V3SchemaConfiguration -} from '@airgap/module-kit' -import { MoonbeamModule } from '@airgap/moonbeam/v1' -import { PolkadotModule } from '@airgap/polkadot/v1' -import { TezosModule } from '@airgap/tezos/v1' -import { Injectable } from '@angular/core' -import { SerializerV3, TransactionSignRequest, TransactionSignResponse, TransactionValidator } from '@airgap/serializer' -import { ICPModule } from '@airgap/icp/v1' - -type LoadedProtocolStatus = 'active' | 'passive' - -interface LoadedMainProtocol { - type: 'main' - status: LoadedProtocolStatus - result: ICoinProtocolAdapter -} - -interface LoadedSubProtocol { - type: 'sub' - status: LoadedProtocolStatus - result: [ICoinProtocolAdapter, ICoinSubProtocolAdapter] -} - -type LoadedProtocol = LoadedMainProtocol | LoadedSubProtocol - -@Injectable({ - providedIn: 'root' -}) -export class ProtocolModuleService { - public async loadProtocols(ignore: string[] = []): Promise<{ - activeProtocols: ICoinProtocol[] - passiveProtocols: ICoinProtocol[] - activeSubProtocols: [ICoinProtocol, ICoinSubProtocol][] - passiveSubProtocols: [ICoinProtocol, ICoinSubProtocol][] - }> { - const modules: AirGapModule[] = [ - new BitcoinModule(), - new EthereumModule(), - new TezosModule(), - new PolkadotModule(), - new CosmosModule(), - new AeternityModule(), - new GroestlcoinModule(), - new MoonbeamModule(), - new AstarModule(), - new ICPModule() - ] - - const loadedProtocols: LoadedProtocol[] = await this.loadFromModules(modules, new Set(ignore)) - - const activeProtocols: ICoinProtocol[] = [] - const passiveProtocols: ICoinProtocol[] = [] - - const activeSubProtocols: [ICoinProtocol, ICoinSubProtocol][] = [] - const passiveSubProtocols: [ICoinProtocol, ICoinSubProtocol][] = [] - - for (const protocol of loadedProtocols) { - if (protocol.type === 'main' && protocol.status === 'active') { - activeProtocols.push(protocol.result) - } - - if (protocol.type === 'main' && protocol.status === 'passive') { - passiveProtocols.push(protocol.result) - } - - if (protocol.type === 'sub' && protocol.status === 'active') { - activeSubProtocols.push(protocol.result) - } - - if (protocol.type === 'sub' && protocol.status === 'passive') { - passiveSubProtocols.push(protocol.result) - } - } - - return { - activeProtocols, - passiveProtocols, - activeSubProtocols, - passiveSubProtocols - } - } - - private async loadFromModules(modules: AirGapModule[], ignore: Set): Promise { - const protocols: LoadedProtocol[][] = await Promise.all( - modules.map(async (module: AirGapModule) => { - const offlineProtocols: string[] = Object.entries(module.supportedProtocols) - .filter( - ([identifier, configuration]: [string, ProtocolConfiguration]) => - configuration.type === 'offline' || (configuration.type === 'full' && !ignore.has(identifier)) - ) - .map(([identifier, _]: [string, ProtocolConfiguration]) => identifier) - - const v3SerializerCompanion: AirGapV3SerializerCompanion = await module.createV3SerializerCompanion() - - this.loadSerializerValidators(v3SerializerCompanion) - - const activeProtocols: Record = {} - const activeSubProtocols: [ICoinProtocolAdapter, ICoinSubProtocolAdapter][] = [] - - for (const identifier of offlineProtocols) { - const adapter: ICoinProtocolAdapter = await this.createProtocolAdapter(module, identifier, v3SerializerCompanion) - - if (adapter instanceof ICoinSubProtocolAdapter) { - const mainIdentifier: string = await adapter.v1Protocol.mainProtocol() - if (mainIdentifier! in activeProtocols) { - const mainAdapter: ICoinProtocolAdapter = await this.createProtocolAdapter(module, mainIdentifier, v3SerializerCompanion) - activeProtocols[mainIdentifier] = mainAdapter - } - - activeSubProtocols.push([activeProtocols[mainIdentifier], adapter]) - } else { - activeProtocols[identifier] = adapter - } - } - - const loadedMainProtocols: LoadedProtocol[] = Object.values(activeProtocols).map((protocol) => ({ - type: 'main', - status: 'active', - result: protocol - })) - - const loadedSubProtocols: LoadedProtocol[] = activeSubProtocols.map((protocol) => ({ - type: 'sub', - status: 'active', - result: protocol - })) - - return loadedMainProtocols.concat(loadedSubProtocols) - }) - ) - - return flattened(protocols) - } - - private async createProtocolAdapter( - module: AirGapModule, - identifier: string, - v3SerializerCompanion: AirGapV3SerializerCompanion - ): Promise { - const [protocol, blockExplorer]: [AirGapOfflineProtocol, AirGapBlockExplorer] = await Promise.all([ - module.createOfflineProtocol(identifier), - module.createBlockExplorer(identifier) - ]) - - return isSubProtocol(protocol) - ? ICoinSubProtocolAdapter.create(protocol, blockExplorer, v3SerializerCompanion) - : ICoinProtocolAdapter.create(protocol, blockExplorer, v3SerializerCompanion) - } - - private loadSerializerValidators(v3SerializerCompanion: AirGapV3SerializerCompanion) { - v3SerializerCompanion.schemas.forEach((configuration: V3SchemaConfiguration) => { - SerializerV3.addSchema(configuration.type, configuration.schema, configuration.protocolIdentifier as ProtocolSymbols) - - if (configuration.protocolIdentifier) { - SerializerV3.addValidator(configuration.protocolIdentifier as ProtocolSymbols, { - create(): TransactionValidator { - return new GenericTransactionValidator(configuration.protocolIdentifier, v3SerializerCompanion) - } - }) - } - }) - } -} - -class GenericTransactionValidator implements TransactionValidator { - public constructor(private readonly protocolIdentifier: string, private readonly serializerCompanion: AirGapV3SerializerCompanion) {} - - public async validateUnsignedTransaction(transaction: TransactionSignRequest): Promise { - return this.serializerCompanion.validateTransactionSignRequest(this.protocolIdentifier, transaction) - } - - public async validateSignedTransaction(transaction: TransactionSignResponse): Promise { - return this.serializerCompanion.validateTransactionSignResponse(this.protocolIdentifier, transaction) - } -} diff --git a/src/app/services/secrets/secrets.service.spec.ts b/src/app/services/secrets/secrets.service.spec.ts index 12be3b1f..c836643a 100644 --- a/src/app/services/secrets/secrets.service.spec.ts +++ b/src/app/services/secrets/secrets.service.spec.ts @@ -1,3 +1,4 @@ +import { ISOLATED_MODULES_PLUGIN, WebIsolatedModules } from '@airgap/angular-core' import { TestBed } from '@angular/core/testing' import { StorageMock } from 'test-config/storage-mock' @@ -20,7 +21,8 @@ describe('SecretsService', () => { providers: [ SecretsService, { provide: VaultStorageService, useClass: StorageMock }, - { provide: SecureStorageService, useClass: SecureStorageServiceMock } + { provide: SecureStorageService, useClass: SecureStorageServiceMock }, + { provide: ISOLATED_MODULES_PLUGIN, useValue: new WebIsolatedModules() } ] }) ) diff --git a/src/app/services/storage/storage.service.ts b/src/app/services/storage/storage.service.ts index 50fa1cba..96ca3ee6 100644 --- a/src/app/services/storage/storage.service.ts +++ b/src/app/services/storage/storage.service.ts @@ -6,7 +6,7 @@ import { Observable, ReplaySubject } from 'rxjs' export enum LanguagesType { EN = 'en', DE = 'de', - ES = 'es', + // ES = 'es', PT_BR = 'pt_BR', ZH_CN = 'zh_CN' } @@ -21,7 +21,8 @@ export enum InteractionType { export enum InstallationType { UNDETERMINED = 'UNDETERMINED', ONLINE = 'ONLINE', - OFFLINE = 'OFFLINE' + OFFLINE = 'OFFLINE', + ALWAYS_ASK = 'ALWAYS_ASK' } // TODO: rename? @@ -41,7 +42,12 @@ export enum VaultStorageKey { INTERACTION_TYPE = 'INTERACTION_TYPE', LANGUAGE_TYPE = 'LANGUAGE_TYPE', INSTALLATION_TYPE = 'INSTALLATION_TYPE', - AIRGAP_SECRET_LIST = 'airgap-secret-list' + AIRGAP_SECRET_LIST = 'airgap-secret-list', + AIRGAP_CONTACTS_LIST = 'airgap-contacts-list', + AIRGAP_CONTACTS_RECOMMENDED_LIST = 'airgap-contacts-recommended-list', + ADDRESS_BOOK_DISABLED = 'ADDRESS_BOOK_DISABLED', + ADDRESS_BOOK_SUGGESTIONS_DISABLED = 'ADDRESS_BOOK_SUGGESTIONS_DISABLED', + ADDRESS_BOOK_ONBOARDING_DISABLED = 'ADDRESS_BOOK_ONBOARDING_DISABLED' } interface VaultStorageKeyReturnType { @@ -55,6 +61,11 @@ interface VaultStorageKeyReturnType { [VaultStorageKey.LANGUAGE_TYPE]: LanguagesType | undefined [VaultStorageKey.INSTALLATION_TYPE]: InstallationType [VaultStorageKey.AIRGAP_SECRET_LIST]: unknown + [VaultStorageKey.AIRGAP_CONTACTS_LIST]: unknown + [VaultStorageKey.AIRGAP_CONTACTS_RECOMMENDED_LIST]: string[] + [VaultStorageKey.ADDRESS_BOOK_DISABLED]: boolean + [VaultStorageKey.ADDRESS_BOOK_SUGGESTIONS_DISABLED]: boolean + [VaultStorageKey.ADDRESS_BOOK_ONBOARDING_DISABLED]: boolean } type VaultStorageKeyReturnDefaults = { [key in VaultStorageKey]: VaultStorageKeyReturnType[key] } @@ -69,7 +80,12 @@ const defaultValues: VaultStorageKeyReturnDefaults = { [VaultStorageKey.INTERACTION_TYPE]: InteractionType.UNDETERMINED, [VaultStorageKey.LANGUAGE_TYPE]: undefined, [VaultStorageKey.INSTALLATION_TYPE]: InstallationType.UNDETERMINED, - [VaultStorageKey.AIRGAP_SECRET_LIST]: [] + [VaultStorageKey.AIRGAP_SECRET_LIST]: [], + [VaultStorageKey.AIRGAP_CONTACTS_LIST]: [], + [VaultStorageKey.AIRGAP_CONTACTS_RECOMMENDED_LIST]: [], + [VaultStorageKey.ADDRESS_BOOK_DISABLED]: false, + [VaultStorageKey.ADDRESS_BOOK_SUGGESTIONS_DISABLED]: false, + [VaultStorageKey.ADDRESS_BOOK_ONBOARDING_DISABLED]: false } @Injectable({ diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index c8225f72..d754003f 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -74,7 +74,8 @@ "medium_text": "Secure communication through app switching." }, "wallet_install_label": "Install AirGap Wallet", - "continue_label": "Let's Go" + "continue_label": "Continue", + "skip_label": "Skip" }, "secret-setup": { "heading": "Secret Setup", @@ -95,7 +96,9 @@ "coin-flip": { "label": "Generate with Coin Flips", "text": "Use a coin to generate a secure and verifiable recovery phrase." - } + }, + "advanced": "Advanced Entropy Generation", + "advanced_warning": "Allows you to use Dice Rolls or Coin Flips as alternative entropy generation methods. Only use these, if you are familiar with them and know the risks involved. Only use a real-world dice or coin" }, "secret-edit": { "title": " Your Secret", @@ -193,6 +196,7 @@ "heading": "Make sure you follow these rules", "text": "We've generated your secret, it's a sequence of words.", "description": "Make sure you understand these rules that ensure you will always have safe access to your accounts.", + "confirm": "Please take notice and click the checkboxes:", "rules-list": { "item-1_text": "Write these words down on a piece of paper", "item-2_text": "The words need to be in order", @@ -204,7 +208,7 @@ "understood_label": "Understood" }, "secret-show": { - "title": "This is your recovery phrase", + "title": "Recovery Phrase", "text": "Write down all words on a piece of paper, remember to follow the rules.", "fingerprint": "Fingerprint", "next-step_label": "Next Step", @@ -281,6 +285,45 @@ "title": "Social Recovery", "text": "Tap each word to match the correct order:" }, + "contact-book": { + "label_add": "Add", + "label_edit": "Edit", + "label_cancel": "Cancel", + "label_finish": "Finish", + "label_close": "Close", + "label_sort_by": "Sort by", + "label_search_contacts": "Search contacts", + "label_added_by": "added by", + "label_name": "Name", + "label_address": "Address", + "label_transactions": "Transactions", + "label_creation_date": "Creation date", + "label_delete_entry": "Delete address entry", + + "title_settings": "Address Book Settings", + "label_enable_suggestions": "Enable suggestions", + "label_enable_address_book": "Enable address book", + "button_delete_entries": "Reset entries", + + "title_address_book": "Address Book", + "label_welcome_personal_address_book": "Welcome to your personal address book", + "label_this_allows_to": "This allows you to", + "label_indentify_addresses_you_interact": "Identify addresses you interact with", + "label_store_manage_entries": "Store and manage address entries", + "label_look_transactions_histories": "Look at relevant transactions histories and much more!", + + "label_add_address_entries": "Add Address Entries", + "label_several_ways": "There's several ways how to add new entries to your address book:", + "label_scan_qr": "Scan the address QR code", + "label_manual_entry": "Manual entry", + "label_recommended_by_us": "Recommended by us", + "label_while_signing": "While signing transactions", + + "label_recommendations": "Recommendations", + "label_recommendation_on_who": "We'll make recommendations on who to add based on addresses you interact with frequently", + "label_suggestions": "Suggestions", + "label_note_disable": "Note: You can disable this option later in the settings" + }, "tab-scan": { "title": "QR Code Scanner", "text": "Scan a QR Code from AirGap Wallet", @@ -313,7 +356,10 @@ "welcome-onboarding_label": "Welcome", "disclaimer_label": "Disclaimer", "installation-type_label": "Installation Type", - "advanced-mode-type_label": "Advanced Mode" + "advanced-mode-type_label": "Advanced Mode", + "advanced-features_label": "Advanced Features", + "address_book_label": "Address Book", + "configure_address_book_label": "Configure Address Book" }, "tab-secrets": { "title": "Secrets", @@ -621,7 +667,8 @@ "message": "An error occured while trying to wipe the app. If this error persists, please uninstall and remove the app from your device.", "ok": "Ok" } - } + }, + "load-module_label": "Load Module" }, "secret-generate-dice-roll": { "title": "Dice Rolls", @@ -651,5 +698,34 @@ "wordlist": { "title": "Wordlist", "search_placeholder": "Search..." + }, + "module-preview": { + "title": "{{ name }} Module Preview", + "install-button_label": "Install", + "manifest": { + "name": { + "label": "Name" + }, + "version": { + "label": "Version" + }, + "author": { + "label": "Author" + }, + "signature": { + "label": "Signature" + }, + "include": { + "description": "Something about the following files being supposed to be copied over and trusting their content." + } + } + }, + "keyboard": { + "paste": "Paste", + "add": "Add Word", + "delete": "Delete Word", + "shuffle": "Shuffle Keys", + "mask": "Mask Text", + "word_list": "Show Word List" } } diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json index 7c5c7193..811dedcc 100644 --- a/src/assets/i18n/es.json +++ b/src/assets/i18n/es.json @@ -198,7 +198,7 @@ "understood_label": "Understood" }, "secret-show": { - "title": "This is your recovery phrase", + "title": "Recovery Phrase", "text": "Write down all words on a piece of paper, remember to follow the rules.", "fingerprint": "Fingerprint", "next-step_label": "Next Step", diff --git a/src/assets/i18n/pt_BR.json b/src/assets/i18n/pt_BR.json index 67c5e1c1..cf10ea21 100644 --- a/src/assets/i18n/pt_BR.json +++ b/src/assets/i18n/pt_BR.json @@ -198,7 +198,7 @@ "understood_label": "Understood" }, "secret-show": { - "title": "This is your recovery phrase", + "title": "Recovery Phrase", "text": "Write down each word on a piece of paper, remember to follow the rules.", "fingerprint": "Fingerprint", "next-step_label": "Next Step", diff --git a/src/assets/native/isolated_modules/isolated-modules.js-engine-android.js b/src/assets/native/isolated_modules/isolated-modules.js-engine-android.js new file mode 100644 index 00000000..3fb30478 --- /dev/null +++ b/src/assets/native/isolated_modules/isolated-modules.js-engine-android.js @@ -0,0 +1,34 @@ +var global = {}; + +function utf8ArrayToString(array) { + var out, i, len, c; + var char2, char3; + + out = ""; + len = array.length; + i = 0; + while (i < len) { + c = array[i++]; + switch (c >> 4) + { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + // 0xxxxxxx + out += String.fromCharCode(c); + break; + case 12: case 13: + // 110x xxxx 10xx xxxx + char2 = array[i++]; + out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); + break; + case 14: + // 1110 xxxx 10xx xxxx 10xx xxxx + char2 = array[i++]; + char3 = array[i++]; + out += String.fromCharCode(((c & 0x0F) << 12) | + ((char2 & 0x3F) << 6) | + ((char3 & 0x3F) << 0)); + break; + } + } + return out; +} \ No newline at end of file diff --git a/src/assets/native/isolated_modules/isolated-modules.script.js b/src/assets/native/isolated_modules/isolated-modules.script.js new file mode 100644 index 00000000..d1b099ca --- /dev/null +++ b/src/assets/native/isolated_modules/isolated-modules.script.js @@ -0,0 +1,292 @@ +/***** UTILS *****/ + +function createOnError(description, handler) { + return (error) => { + var fullDescription + if (typeof error === 'string') { + if (typeof description === 'string') { + fullDescription = `${description} (${error})` + } else { + fullDescription = error + } + } else if (typeof error === 'object' && (typeof error.stack === 'string' || typeof error.message === 'string')) { + if (typeof description === 'string') { + fullDescription = `${description} (${error.stack || error.message})` + } else { + fullDescription = error.stack || error.message + } + } else { + if (typeof description === 'string') { + fullDescription = description + } else { + fullDescription = "Unknown error" + } + } + + handler(fullDescription) + } +} + +const UNDEFINED_STRING = 'it.airgap.vault.__UNDEFINED__' + +function replaceUndefined(value) { + if (Array.isArray(value)) { + return value.map((v) => replaceUndefined(v)) + } + + if (typeof value === 'object') { + return Object.entries(value).reduce((obj, [key, value]) => Object.assign(obj, { [key]: replaceUndefined(value) }), {}) + } + + return typeof value === 'string' && value === UNDEFINED_STRING + ? undefined + : value +} + +function flattened(array) { + if (!Array.isArray(array)) return array + + return array.reduce((acc, next) => { + return acc.concat(Array.isArray(next) ? next : [next]) + }, []) +} + +function collectMethods(protocol) { + let propertyNames = [] + let obj = protocol + while (obj) { + propertyNames = propertyNames.concat(Object.getOwnPropertyNames(obj)) + obj = Object.getPrototypeOf(obj) + } + + return propertyNames.filter((key) => typeof protocol[key] === 'function') +} + +function isSubProtocol(protocol) { + return typeof protocol === 'object' && 'getType' in protocol && 'mainProtocol' in protocol +} + +function hasConfigurableContract(protocol) { + return isSubProtocol(protocol) && 'isContractValid' in protocol && 'getContractAddress' in protocol && 'setContractAddress' in protocol +} + +/***** LOAD *****/ + +const PROTOCOL_TYPE_OFFLINE = 'offline' +const PROTOCOL_TYPE_ONLINE = 'online' +const PROTOCOL_TYPE_FULL = 'full' + +const ISOLATED_PROTOCOL_MODE_OFFLINE = 'offline' +const ISOLATED_PROTOCOL_MODE_ONLINE = 'online' + +const ISOLATED_PROTOCOL_TYPE_MAIN = 'main' +const ISOLATED_PROTOCOL_TYPE_SUB = 'sub' + +function getIsolatedProtocolConfiguration(protocol, mode, blockExplorerMetadata, network, crypto) { + return protocol.getMetadata() + .then((protocolMetadata) => { + const configuration = { + mode, + identifier: protocolMetadata.identifier, + protocolMetadata, + blockExplorerMetadata: blockExplorerMetadata ? blockExplorerMetadata : null, + network: network ? network : null, + crypto: crypto ? crypto : null, + methods: collectMethods(protocol) + } + + if (isSubProtocol(protocol)) { + return Promise.all([ + protocol.getType(), + protocol.mainProtocol(), + hasConfigurableContract(protocol) ? protocol.getContractAddress() : Promise.resolve(undefined) + ]).then(([subType, mainProtocol, contractAddress]) => ({ + ...configuration, + type: ISOLATED_PROTOCOL_TYPE_SUB, + subType, + mainProtocolIdentifier: mainProtocol, + contractAddress: contractAddress ?? null + })) + } else { + return { + ...configuration, + type: ISOLATED_PROTOCOL_TYPE_MAIN + } + } + }) +} + +function loadOfflineProtocolMetadata(module, protocolIdentifier) { + return module.createOfflineProtocol(protocolIdentifier) + .then((protocol) => { + if (protocol === undefined) { + return [] + } + + return protocol.getCryptoConfiguration() + .then((crypto) => getIsolatedProtocolConfiguration(protocol, ISOLATED_PROTOCOL_MODE_OFFLINE, undefined, undefined, crypto)) + .then((isolatedProtocol) => [isolatedProtocol]) + }) +} + +function loadOnlineProtocolMetadata(module, protocolIdentifier, configuration) { + return Promise.all( + Object.entries(configuration.networks).map(([networkId, _]) => { + return Promise.all([ + module.createOnlineProtocol(protocolIdentifier, networkId), + module.createBlockExplorer(protocolIdentifier, networkId) + ]).then(([protocol, blockExplorer]) => { + if (protocol === undefined) { + return undefined + } + + return Promise.all([ + protocol.getNetwork(), + blockExplorer ? blockExplorer.getMetadata() : Promise.resolve(undefined) + ]).then(([network, blockExplorerMetadata]) => getIsolatedProtocolConfiguration(protocol, ISOLATED_PROTOCOL_MODE_ONLINE, blockExplorerMetadata, network)) + }) + }) + ).then((isolatedProtocols) => isolatedProtocols.filter((protocol) => protocol !== undefined)) +} + +function loadProtocolMetadataFromConfiguration(module, protocolIdentifier, configuration, protocolType) { + const offlineConfiguration = + protocolType === PROTOCOL_TYPE_OFFLINE || protocolType === PROTOCOL_TYPE_FULL || protocolType === undefined + ? configuration.type === PROTOCOL_TYPE_OFFLINE + ? configuration + : configuration.type === PROTOCOL_TYPE_FULL + ? configuration.offline + : undefined + : undefined + + const onlineConfiguration = + protocolType === PROTOCOL_TYPE_ONLINE || protocolType === PROTOCOL_TYPE_FULL || protocolType === undefined + ? configuration.type === PROTOCOL_TYPE_ONLINE + ? configuration + : configuration.type === PROTOCOL_TYPE_FULL + ? configuration.online + : undefined + : undefined + + return Promise.all([ + offlineConfiguration ? loadOfflineProtocolMetadata(module, protocolIdentifier) : Promise.resolve([]), + onlineConfiguration ? loadOnlineProtocolMetadata(module, protocolIdentifier, onlineConfiguration) : Promise.resolve([]) + ]).then(([offline, online]) => offline.concat(online)) +} + +function loadProtocols(module, protocolType) { + return Promise.all( + Object.entries(module.supportedProtocols).map(([protocolIdentifier, configuration]) => loadProtocolMetadataFromConfiguration(module, protocolIdentifier, configuration, protocolType)) + ).then((protocols) => flattened(protocols)) +} + +function load(namespace, moduleIdentifier, action) { + const module = namespace ? namespace.create() : create() + + return module.createV3SerializerCompanion() + .then((v3SerializerCompanion) => + loadProtocols(module, action.protocolType).then((protocols) => ({ identifier: moduleIdentifier, protocols, v3SchemaConfigurations: v3SerializerCompanion.schemas })) + ) +} + +/***** CALL METHOD *****/ + +function callOfflineProtocolMethod(namespace, protocolIdentifier, method, args) { + const module = namespace ? namespace.create() : create() + return module.createOfflineProtocol(protocolIdentifier) + .then((protocol) => { + if (protocol === undefined) { + return undefined + } + + return protocol[method](...args) + }) + .then((value) => ({ value })) +} + +function callOnlineProtocolMethod(namespace, protocolIdentifier, networkId, method, args) { + const module = namespace ? namespace.create() : create() + return module.createOnlineProtocol(protocolIdentifier, networkId) + .then((protocol) => { + if (protocol === undefined) { + return undefined + } + + return protocol[method](...args) + }) + .then((value) => ({ value })) +} + +function callBlockExplorerMethod(namespace, protocolIdentifier, networkId, method, args) { + const module = namespace ? namespace.create() : create() + return module.createBlockExplorer(protocolIdentifier, networkId) + .then((blockExplorer) => { + if (blockExplorer === undefined) { + return undefined + } + + return blockExplorer[method](...args) + }) + .then((value) => ({ value })) +} + +function callV3SerializerCompanionMethod(namespace, method, args) { + const module = namespace ? namespace.create() : create() + return module.createV3SerializerCompanion() + .then((v3SerializerCompanion) => { + if (v3SerializerCompanion === undefined) { + return undefined + } + + return v3SerializerCompanion[method](...args) + }) + .then((value) => ({ value })) +} + +const CALL_METHOD_TARGET_OFFLINE_PROTOCOL = 'offlineProtocol' +const CALL_METHOD_TARGET_ONLINE_PROTOCOL = 'onlineProtocol' +const CALL_METHOD_TARGET_BLOCK_EXPLORER = 'blockExplorer' +const CALL_METHOD_TARGET_V3_SERIALIZER_COMPANION = 'v3SerializerCompanion' + +function callMethod(namespace, action) { + switch (action.target) { + case CALL_METHOD_TARGET_OFFLINE_PROTOCOL: + return callOfflineProtocolMethod(namespace, action.protocolIdentifier, action.method, action.args) + case CALL_METHOD_TARGET_ONLINE_PROTOCOL: + return callOnlineProtocolMethod(namespace, action.protocolIdentifier, action.networkId, action.method, action.args) + case CALL_METHOD_TARGET_BLOCK_EXPLORER: + return callBlockExplorerMethod(namespace, action.protocolIdentifier, action.networkId, action.method, action.args) + case CALL_METHOD_TARGET_V3_SERIALIZER_COMPANION: + return callV3SerializerCompanionMethod(namespace, action.method, action.args) + } +} + +/***** EXECUTE *****/ + +const ACTION_LOAD = 'load' +const ACTION_CALL_METHOD = 'callMethod' + +function execute(namespace, moduleIdentifier, action, handleResult, handleError) { + const errorHandler = (description) => { + const prefixedDescription = `[${moduleIdentifier}]${description ? ' ' + description : ''}` + return createOnError(prefixedDescription, (error) => { + console.error(error) + handleError(error) + }) + } + + try { + switch (action.type) { + case ACTION_LOAD: + load(namespace, moduleIdentifier, replaceUndefined(action)).then(handleResult).catch(errorHandler('load')) + break + case ACTION_CALL_METHOD: + callMethod(namespace, replaceUndefined(action)).then(handleResult).catch(errorHandler('call method')) + break + default: + throw new Error(`Unknown action ${action.type}`) + } + } catch (error) { + errorHandler()(error) + } +} \ No newline at end of file diff --git a/src/assets/native/isolated_modules/protocol_common.js b/src/assets/native/isolated_modules/protocol_common.js deleted file mode 100644 index 9f520a1d..00000000 --- a/src/assets/native/isolated_modules/protocol_common.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - * START PLATFORM DEFINED - */ - -/*** START required ***/ - -var identifier = __platform__identifier /* : string */ -var options = __platform__options /* : object */ -var action = __platform__action /* : 'getField' | 'callMethod */ - -var handleError = __platform__handleError /* : function(error: string) */ -var handleResult = __platform__handleResult /* : function(result: any) */ - -/*** END required ***/ - -/*** START optional ***/ - -var field = typeof __platform__field !== 'undefined' ? __platform__field : undefined /* : string */ - -var method = typeof __platform__method !== 'undefined' ? __platform__method : undefined /* : string */ -var args = typeof __platform__args !== 'undefined' ? __platform__args : undefined /* : [any] */ - -/*** END optional ***/ - -/** - * END PLATFORM DEFINED - */ - -function createOnError(description, handler) { - return function(error) { - var fullDescription - if (typeof error === 'string') { - if (typeof description === 'string') { - fullDescription = `${description} (${error})` - } else { - fullDescription = error - } - } else if (typeof error === 'object' && typeof error.message === 'string') { - if (typeof description === 'string') { - fullDescription = `${description} (${error.message})` - } else { - fullDescription = error.message - } - } else { - if (typeof description === 'string') { - fullDescription = description - } else { - fullDescription = "Unknown error" - } - } - - handler(fullDescription) - } -} - -function onError(description) { - return createOnError(description, function(error) { - handleError(error) - }) -} - -function loadCoinlib(callback) { - airgapCoinLib.isCoinlibReady().then(callback).catch(onError()) -} - -function createProtocol(identifier, options) { - return airgapCoinLib.createProtocolByIdentifier(identifier, options) -} - -function getField(protocol, field, callback) { - callback(protocol[field]) -} - -function callMethod(protocol, method, args, callback) { - protocol[method](...args).then(callback).catch(onError()) -} - -loadCoinlib(function() { - var protocol = createProtocol(identifier, options) - switch (action) { - case 'getField': - getField(protocol, field, handleResult) - break - case 'callMethod': - callMethod(protocol, method, args, handleResult) - break - default: - throw new Error(`Unknown action ${action}`) - } -}) \ No newline at end of file diff --git a/src/theme/variables.scss b/src/theme/variables.scss index 2d9e7998..dcdbb2be 100644 --- a/src/theme/variables.scss +++ b/src/theme/variables.scss @@ -98,6 +98,8 @@ airgap-interaction-selection-settings, airgap-languages-selection-settings, airgap-deserialized-detail, airgap-transaction-signed, +airgap-contact-book-contacts-detail, +airgap-contact-book-onboarding, airgap-secret-generate-onboarding, airgap-social-recovery-setup, airgap-secret-generate, diff --git a/test-config/plugins-mocks.ts b/test-config/plugins-mocks.ts index 982191e2..ab1bad5e 100644 --- a/test-config/plugins-mocks.ts +++ b/test-config/plugins-mocks.ts @@ -1,7 +1,8 @@ // tslint:disable: max-classes-per-file -import { AppInfoPlugin } from '@airgap/angular-core' +import { AppInfoPlugin, IsolatedModulesPlugin, ZipPlugin } from '@airgap/angular-core' import { AppPlugin } from '@capacitor/app' import { ClipboardPlugin } from '@capacitor/clipboard' +import { FilesystemPlugin } from '@capacitor/filesystem' import { SplashScreenPlugin } from '@capacitor/splash-screen' import { StatusBarPlugin } from '@capacitor/status-bar' @@ -56,6 +57,18 @@ export function createStatusBarSpy(): StatusBarPlugin { return jasmine.createSpyObj('StatusBarPlugin', ['setStyle', 'setBackgroundColor']) } +export function createFilesystemSpy(): FilesystemPlugin { + return jasmine.createSpyObj('FilesystemPlugin', ['stat', 'mkdir', 'rmdir', 'readdir', 'readFile', 'copy']) +} + +export function createZipSpy(): ZipPlugin { + return jasmine.createSpyObj('ZipPlugin', ['unzip']) +} + +export function createIsolatedModulesSpy(): IsolatedModulesPlugin { + return jasmine.createSpyObj('IsolatedModulesPlugin', ['loadModules', 'callMethod']) +} + export class AppInfoPluginMock { public get: jasmine.Spy = newSpy( 'set', diff --git a/yarn.lock b/yarn.lock index bfb46ab9..1ff9da6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,44 +2,62 @@ # yarn lockfile v1 -"@airgap/aeternity@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/aeternity/-/aeternity-0.13.10.tgz#a56201d4a6e2291c587bead94d49a9a8c6dbcabb" - integrity sha512-9qo7E6JI6jrq/T/SrS12vB9WTeUcLhb/WGYjJYAPbvwOGKw9fqGdDQWe/4UXdCF6QhOs27qmKZG6yCIADD+hMg== +"7zip-bin@~4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-4.1.0.tgz#33eff662a5c39c0c2061170cc003c5120743fff0" + integrity sha512-AsnBZN3a8/JcNt+KPkGGODaA4c7l3W5+WpeKgGSbstSLxqWtTXqd1ieJGBQ8IFCtRg8DmmKUcSkIkUc0A4p3YA== + +"@airgap/aeternity@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/aeternity/-/aeternity-0.13.11.tgz#c6f3b9bbdc5a8e25a24c83c2f8aa5b26c7b69d29" + integrity sha512-OznWplAuF4WAKN9pVfYeMpBV2BNL/XqPPNqI6Pu9U6TyjmgwOPxEd1dJSBrCvEBgWjEGcHfdTTpcIfEFuW3dcA== + dependencies: + "@airgap/coinlib-core" "*" + "@airgap/module-kit" "*" + "@airgap/serializer" "*" + "@stablelib/ed25519" "^1.0.3" -"@airgap/angular-core@0.0.34": - version "0.0.34" - resolved "https://registry.yarnpkg.com/@airgap/angular-core/-/angular-core-0.0.34.tgz#b323db35dfee6ef58ac42da67d8c658e8eba078a" - integrity sha512-ytScGb8cOGVytXBU/3T/AbcqBqlYRNt+a/rHW4Cm0tcCezwCx7Z7bjjFtI27POy+VLqvGK78hSanamKQmiCo0A== +"@airgap/angular-core@0.0.35": + version "0.0.35" + resolved "https://registry.yarnpkg.com/@airgap/angular-core/-/angular-core-0.0.35.tgz#f7145b09ae8e13306d3cbdd8e5001e3d012cc5f6" + integrity sha512-8AR8CxOOdlBuEao5dbz0AOLzdunrspWhM+e3CCYHTaJ0drxL73TKiWB3B0OSmqsJB+ioMfs3e9fb5Kx+R45FWw== dependencies: tslib "^2.2.0" -"@airgap/angular-ngrx@0.0.34": - version "0.0.34" - resolved "https://registry.yarnpkg.com/@airgap/angular-ngrx/-/angular-ngrx-0.0.34.tgz#292a8ae9f8a94c28431a11d952b8ed5470eb8d3f" - integrity sha512-x1SmEZOVIJnkT9LzNsHeDor8KNdnNbHFU+rWI2D6pjXxfVati3qvdHpoh09DLZs2qm6V+Pl6awzxF0ay7yGuRQ== +"@airgap/angular-ngrx@0.0.35": + version "0.0.35" + resolved "https://registry.yarnpkg.com/@airgap/angular-ngrx/-/angular-ngrx-0.0.35.tgz#7d37929359984d410c2ab5bab6e6faa7c0dc0f89" + integrity sha512-2HWWzTZCeCEcRBAWRrtyMl6uwu9CdFpDlJEZcCsNqJOWXKbvped6CC2xRTnJjnwUdDzEHh1rZK85UH6EdAQYCQ== dependencies: tslib "^2.2.0" -"@airgap/astar@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/astar/-/astar-0.13.10.tgz#a321c16ef467c0b7ea449e29d7b29512ec8623df" - integrity sha512-BYK5auV2xeJ9gHVUSbkKa5vAdjCnU+Gs4jQltKUz+rn3RySbWakzM4S+4AdXfRvQap5lCMCIh+Tt1oB9fdldDg== +"@airgap/astar@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/astar/-/astar-0.13.11.tgz#65bb6154a56e612571057ebb53b3f71eba1328f0" + integrity sha512-RmSEpUZjJDg4kZz072PFjcr4BFsgFklX9NxD3H14ti05wogrfffh4tpRZ2e1Fiutk0untzMXF+5RnTKWr+EE8Q== dependencies: + "@airgap/coinlib-core" "*" + "@airgap/module-kit" "*" + "@airgap/serializer" "*" + "@airgap/substrate" "*" "@polkadot/util" "2.0.1" "@polkadot/wasm-crypto" "0.20.1" -"@airgap/bitcoin@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/bitcoin/-/bitcoin-0.13.10.tgz#f7ea1d2584e7cfd6c87b4235181ed641a67dd0d6" - integrity sha512-VEp0ezgxwIco6ubyxN+ey/sK+cDgrIaAV7H0W2ymNVX3xuiHFE3O1m5s8pIid+CtcYrKQ5A1jTakUbMqOAXJcA== +"@airgap/bitcoin@*", "@airgap/bitcoin@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/bitcoin/-/bitcoin-0.13.11.tgz#a90a97841046af5894a4b4c6943719301934e4a1" + integrity sha512-e7etADjHZTjd1UGVCbBfsubkIzgBn0GuCmDy4KrVpxnzzYYrJ8NQ+Ol4ZMymBZT2iljZV/WB04QqBQcjASMsMA== dependencies: + "@airgap/coinlib-core" "*" + "@airgap/crypto" "*" + "@airgap/module-kit" "*" + "@airgap/serializer" "*" bitcoinjs-lib "5.2.0" -"@airgap/coinlib-core@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/coinlib-core/-/coinlib-core-0.13.10.tgz#3c94325032980e815e03488e7f6967e37957a23a" - integrity sha512-VNmDCSzZJh47z93ORbHEn6dBQ7VzlLtqqcRC4W/0jmpdse5VXuhvR5DhxcotehTkSQRLiGmn+PevnyKGenkZbQ== +"@airgap/coinlib-core@*", "@airgap/coinlib-core@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/coinlib-core/-/coinlib-core-0.13.11.tgz#89190283afbaa22f69e019c93a14045038489c76" + integrity sha512-v094u3tMvelOW7YPgv1NLurDsbvD5YhXAjNHw88GAy64PMmEO82nX9CrdbW2Ipj1bzpwzBwecASFsEVrEVF+Sg== dependencies: "@stablelib/blake2b" "^1.0.1" "@stablelib/bytes" "^1.0.1" @@ -49,78 +67,158 @@ long "^5.2.0" protobufjs "^6.11.2" -"@airgap/cosmos@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/cosmos/-/cosmos-0.13.10.tgz#334959011ea9ceb522eb07eb71b116238d94bb49" - integrity sha512-Cwazb8CjrqekCw01eguvRwpts5l+eVYMSoG8CWEsLUdheLh24UusmaouuJUr4uOM7rXVFVlHS0dWK6L3b7S/Hw== +"@airgap/coreum@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/coreum/-/coreum-0.13.11.tgz#a3c3a7a7590e5717a5677c4c999df103456301b6" + integrity sha512-y9+l2jJtc86emL62ktvdOuObL9In+jp5BQkrH/FteOBgxrlM9hiPMi5q5sjthApl9bNbMxovgdm5iBLTIPFofw== + dependencies: + "@airgap/coinlib-core" "*" + "@airgap/cosmos-core" "*" + "@airgap/crypto" "*" + "@airgap/module-kit" "*" + "@airgap/serializer" "*" + +"@airgap/cosmos-core@*", "@airgap/cosmos-core@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/cosmos-core/-/cosmos-core-0.13.11.tgz#38c1be562c7e2768b9ffefff7313c78d6530d250" + integrity sha512-QjzRpsNfxOS6duf1kDTRyyZ40tIIyLh0br5Jul0bZrKqCUEQUdm8Jw88QebgfjDgiCvqgIR6z9praYLti4oB8g== + dependencies: + "@airgap/coinlib-core" "*" + "@airgap/crypto" "*" + "@airgap/module-kit" "*" + "@airgap/serializer" "*" + +"@airgap/cosmos@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/cosmos/-/cosmos-0.13.11.tgz#2f66da17c7075bf31bf38134a2129603b89b8708" + integrity sha512-CGXpd5EoDkBXtzLPW2ZanbylqtwJvy22LOdquKUdrtGExnJeS+sAUHIxJOT5cwUK7uYY0d0bpe6gJ2g1UZKnSg== + dependencies: + "@airgap/coinlib-core" "*" + "@airgap/cosmos-core" "*" + "@airgap/crypto" "*" + "@airgap/module-kit" "*" + "@airgap/serializer" "*" + +"@airgap/crypto@*", "@airgap/crypto@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/crypto/-/crypto-0.13.11.tgz#e3705cd81b375d2e35a3a9dde2ef80bbd3f29b43" + integrity sha512-BZkpRXwMk1yWrLpgVy29jukZ6k5PrFQGvoE81CFkyodA586aI35cBLJ5+jMPLI/X11uCW8SH2TzvEMSbrRmmRQ== + dependencies: + "@airgap/coinlib-core" "*" + "@airgap/module-kit" "*" + "@airgap/sapling-wasm" "^0.0.9" + "@polkadot/wasm-crypto" "0.20.1" + "@stablelib/hmac" "^1.0.1" -"@airgap/ethereum@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/ethereum/-/ethereum-0.13.10.tgz#3ef0b3dc3973da14a8ea95182e014a907ab1a742" - integrity sha512-y2lQQvo4foLbQ21NbHxiJ7Oad9K5bVqdo2qP4REDmtWfOFCa7grsNjp8X8akNZlBmLF42PvB3Zl2JGY0//z6xw== +"@airgap/ethereum@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/ethereum/-/ethereum-0.13.11.tgz#48a3f12970b7bc42551fb5afc48a3acdfdab4bc9" + integrity sha512-VIrEXKc9KTjOUUSMfJRJxFue/XBhH0+mo+cOQMjYSulOdEf51rzFgDIfVVrAm1fijboAOSFM2nH7RPFxC3RxHA== dependencies: + "@airgap/coinlib-core" "*" + "@airgap/crypto" "*" + "@airgap/module-kit" "*" + "@airgap/serializer" "*" "@ethereumjs/common" "2.6.0" "@ethereumjs/tx" "3.4.0" "@metamask/eth-sig-util" "4.0.0" -"@airgap/groestlcoin@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/groestlcoin/-/groestlcoin-0.13.10.tgz#37118369d7b956d78d3eef7b57c580f42a5e20f3" - integrity sha512-mASwcbYUQlDjkX/kDxD3n+HxwpCV/7hInLcJAFEtbCArYExVL+RpSdLx3LeFQ9WfdL3IJX1fujBzeA4xA4gKhg== - -"@airgap/icp@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/icp/-/icp-0.13.10.tgz#4bb26923d04d4a5e0b2955075c8f9fc4697b4694" - integrity sha512-PfT6N0ho9S99Qh4K1UgrU6htmvHMDsiqEgdfJvIFdR8ledkcD8ZvJD4X8Jbxrq6T1RAjwbLKLbau7+sgL1k+jQ== - dependencies: - "@dfinity/candid" "^0.15.1" - "@dfinity/identity-secp256k1" "^0.15.1" - "@dfinity/nns" "^0.10.0" - "@dfinity/principal" "^0.15.1" - "@dfinity/utils" "^0.0.6" +"@airgap/groestlcoin@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/groestlcoin/-/groestlcoin-0.13.11.tgz#0c8276b9bdc787e535ba58d26bd34e4950bddad1" + integrity sha512-tXSDmPsaaWXVxbQUw+CYhCIa+lpbdwU75jcSbpENZ33PCq/eohunHv+T0Q3UAbv4ovzhmvFLyUDM+Ezp9ECf5A== + dependencies: + "@airgap/bitcoin" "*" + "@airgap/coinlib-core" "*" + "@airgap/module-kit" "*" + "@airgap/serializer" "*" + +"@airgap/icp@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/icp/-/icp-0.13.11.tgz#e03ba62305eb61f65da71c523ee03047ee1036f1" + integrity sha512-uSPud7JAzMwcc06FddEXpQ1cDCQpK/q2XOXxgE/porZb73v7RZ4ZxJixxT6vvoXg8PRhOTv/IkRLgjhgVItBbw== + dependencies: + "@airgap/coinlib-core" "*" + "@airgap/crypto" "*" + "@airgap/module-kit" "*" + "@airgap/serializer" "*" + "@stablelib/ed25519" "^1.0.3" + base64-arraybuffer "^1.0.2" + bip39 "^3.0.4" + borc "^3.0.0" + crc "4.3.2" + crc-32 "1.2.2" isomorphic-fetch "^3.0.0" js-sha256 "^0.9.0" secp256k1 "^5.0.0" + simple-cbor "^0.4.1" -"@airgap/module-kit@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/module-kit/-/module-kit-0.13.10.tgz#faf433dd60bdc69c2783626ef09753f752c498d0" - integrity sha512-nv1Qg+XYXa8pWHB9/M9pVQvB2Immq4utLFHPDcz9TftOcZ0giC7cQqik0zrH4aX7kfCCj7xqa1HzIhlXfyPikg== +"@airgap/module-kit@*", "@airgap/module-kit@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/module-kit/-/module-kit-0.13.11.tgz#f5e9bbd6c3312d22233c79adb1bdd310d57124ff" + integrity sha512-NBjtCv3lyTe0ula8/GO/D3rU1/KngDDGi7G7NgnxzeKHDAnxFFkdJ9Zzft+V1htLPGJBex1i6K/T8lZBy/5ybw== + dependencies: + "@airgap/coinlib-core" "*" + "@airgap/serializer" "*" -"@airgap/moonbeam@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/moonbeam/-/moonbeam-0.13.10.tgz#064af4980042048a58760f093851030bd9a81365" - integrity sha512-TCWeCblSCaJDJOj1G7Ic9hUHLeVuU/ZZ37lbTOGxJwnTgAdipRgoHUZv1E6PG17gDQjE2gXPIFbS9HwyVBbnjw== +"@airgap/moonbeam@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/moonbeam/-/moonbeam-0.13.11.tgz#984ac462e80e657f96252cbd19fec5919f74b684" + integrity sha512-Y7Gu+d7XqYXOOe+gb0cOnn4gFqhY/WutnBX0sEVFj2F9BUu16Y5klEfAZkGdb/NtXw9rEqvDcVMtktJG14fADQ== + dependencies: + "@airgap/coinlib-core" "*" + "@airgap/module-kit" "*" + "@airgap/serializer" "*" + "@airgap/substrate" "*" -"@airgap/polkadot@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/polkadot/-/polkadot-0.13.10.tgz#1f33f479209afdbcf34125c823f2e8e0d31eea60" - integrity sha512-MyrEK9QolL+OrH57c62EbWq8C3p0ARse90vgpBEL7Q9BetOMzDDETQXKWn3vkgRBhFXl+WF7NA7LfgOUq6txfg== +"@airgap/polkadot@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/polkadot/-/polkadot-0.13.11.tgz#f452d898d3d8435e33869dfbb7855fbe0ab6b2ad" + integrity sha512-arIkGz++ACExZbPrLC9NNrTk/96owCJ5JxJP93lxTkKy2qsZNvYUnISxEHVmcaLZ3u7xKL3AwB2k9Zqm7rjTHQ== + dependencies: + "@airgap/coinlib-core" "*" + "@airgap/module-kit" "*" + "@airgap/substrate" "*" "@airgap/sapling-wasm@0.0.7": version "0.0.7" resolved "https://registry.yarnpkg.com/@airgap/sapling-wasm/-/sapling-wasm-0.0.7.tgz#b88356f44807bf91405a9dc7c4111c995f269343" integrity sha512-IMODbGPTBYKuO5ztiHX9C1PTlhqZvmVWv7m7zj5+VMcbBxrk4+jBAf7FYTH5l+IUsNMaHBOuh8Qq3A1b/pm7jQ== -"@airgap/serializer@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/serializer/-/serializer-0.13.10.tgz#9bfe4d7e9b20c2c05e53fe5b383c7927e919cb7d" - integrity sha512-HVTpd05G6PPj6/hnZs+oBL/cWP543AMxp93GHrg3KsWQPBFLvxpgxhrzCXYaPcXyxgSHSbOlRttOVOzgi8HEtw== +"@airgap/sapling-wasm@^0.0.9": + version "0.0.9" + resolved "https://registry.yarnpkg.com/@airgap/sapling-wasm/-/sapling-wasm-0.0.9.tgz#641b588822179a1659e248a84ad971e16461fc6b" + integrity sha512-rJjV7JIDxoardnZMgk4Uor5Z6OVsAE4I5uDlkGAb0tQ5NN0gmz9Bu2LKMPSCv7UqDpZowDX4BbMDuSqdO/IsbQ== + +"@airgap/serializer@*", "@airgap/serializer@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/serializer/-/serializer-0.13.11.tgz#515a5173fd4687c68c9ee9619ca2c6c199c5532b" + integrity sha512-yLJQTiSd19QQiNmkJ2CLJboRryDt+QS89+1ZqxuGfHb2bBmUxUl/unksLwYmSKLzsOYdAJNPOG5gAailXRKkng== + dependencies: + "@airgap/coinlib-core" "*" -"@airgap/substrate@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/substrate/-/substrate-0.13.10.tgz#e8a2833fd1bf2a8726d4d30eb529d26b4c1dc5f8" - integrity sha512-nUM0S6q4iqVvqbnAoO+5CMZrdcPuYQSnnz/X0yYaEg1jQlGANI4RgKy8aipB85qaVEuehpMC/lJjqQh3lKY83g== +"@airgap/substrate@*", "@airgap/substrate@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/substrate/-/substrate-0.13.11.tgz#e03bdc8d0e9b57b48a5461a5c465ec189dfdc10d" + integrity sha512-2q2NNN+5D3PoV+DUqOEsakObzI2nIBCyCmnRmmESITZJJe1/Dl/30SF2jB6fTDuH69j9yI3B8ciYLWGxR1OBTg== dependencies: + "@airgap/coinlib-core" "*" + "@airgap/crypto" "*" + "@airgap/module-kit" "*" + "@airgap/serializer" "*" "@polkadot/util" "2.0.1" "@polkadot/wasm-crypto" "0.20.1" -"@airgap/tezos@0.13.10": - version "0.13.10" - resolved "https://registry.yarnpkg.com/@airgap/tezos/-/tezos-0.13.10.tgz#0f37f62a21952418596c4afc5029754139d93ee0" - integrity sha512-u3ZTeg6/Pn7ZR7K5QB164fVB3zg9xO08xvEPXe+23mV2vwMQH3Wruenmc7P6OInfXjGfwUZgb48yxAiVLiQUrQ== +"@airgap/tezos@0.13.11": + version "0.13.11" + resolved "https://registry.yarnpkg.com/@airgap/tezos/-/tezos-0.13.11.tgz#645cbc76c80871537e93eb6fc47587d2da2d97b1" + integrity sha512-ktUMM84L6ACaPUDu3ms0ui96QfHJH2SZIFKQaflnHyytbbljyj3WoaxFWYfsEYs8I9k+Lv5HJ18id2Q3JyXXNA== dependencies: + "@airgap/coinlib-core" "*" + "@airgap/crypto" "*" + "@airgap/module-kit" "*" "@airgap/sapling-wasm" "0.0.7" + "@airgap/serializer" "*" "@stablelib/blake2b" "^1.0.1" "@stablelib/ed25519" "^1.0.3" "@stablelib/nacl" "^1.0.4" @@ -138,7 +236,7 @@ "@jridgewell/resolve-uri" "^3.0.3" sourcemap-codec "1.4.8" -"@ampproject/remapping@^2.1.0": +"@ampproject/remapping@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== @@ -393,9 +491,9 @@ "@babel/highlight" "^7.18.6" "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.5": - version "7.20.10" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.10.tgz#9d92fa81b87542fff50e848ed585b4212c1d34ec" - integrity sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.0.tgz#c241dc454e5b5917e40d37e525e2f4530c399298" + integrity sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g== "@babel/core@7.16.12": version "7.16.12" @@ -419,20 +517,20 @@ source-map "^0.5.0" "@babel/core@^7.12.3", "@babel/core@^7.17.2": - version "7.20.12" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7930db57443c6714ad216953d1356dac0eb8496d" - integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.0.tgz#1341aefdcc14ccc7553fcc688dd8986a2daffc13" + integrity sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA== dependencies: - "@ampproject/remapping" "^2.1.0" + "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.7" + "@babel/generator" "^7.21.0" "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helpers" "^7.20.7" - "@babel/parser" "^7.20.7" + "@babel/helper-module-transforms" "^7.21.0" + "@babel/helpers" "^7.21.0" + "@babel/parser" "^7.21.0" "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.12" - "@babel/types" "^7.20.7" + "@babel/traverse" "^7.21.0" + "@babel/types" "^7.21.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -448,13 +546,14 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/generator@^7.16.8", "@babel/generator@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.7.tgz#f8ef57c8242665c5929fe2e8d82ba75460187b4a" - integrity sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw== +"@babel/generator@^7.16.8", "@babel/generator@^7.21.0": + version "7.21.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" + integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== dependencies: - "@babel/types" "^7.20.7" + "@babel/types" "^7.21.0" "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" "@babel/helper-annotate-as-pure@7.16.7": @@ -490,27 +589,27 @@ lru-cache "^5.1.1" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.5", "@babel/helper-create-class-features-plugin@^7.20.7": - version "7.20.12" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.12.tgz#4349b928e79be05ed2d1643b20b99bb87c503819" - integrity sha512-9OunRkbT0JQcednL0UFvbfXpAsUXiGjUk0a7sN8fUXX7Mue79cUSMjHGDRRi/Vz9vYlpIhLV5fMD5dKoMhhsNQ== +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz#64f49ecb0020532f19b1d014b03bccaa1ab85fb9" + integrity sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-member-expression-to-functions" "^7.20.7" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-member-expression-to-functions" "^7.21.0" "@babel/helper-optimise-call-expression" "^7.18.6" "@babel/helper-replace-supers" "^7.20.7" "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" "@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.20.5": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz#5ea79b59962a09ec2acf20a963a01ab4d076ccca" - integrity sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.0.tgz#53ff78472e5ce10a52664272a239787107603ebb" + integrity sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" - regexpu-core "^5.2.1" + regexpu-core "^5.3.1" "@babel/helper-define-polyfill-provider@^0.3.1", "@babel/helper-define-polyfill-provider@^0.3.2", "@babel/helper-define-polyfill-provider@^0.3.3": version "0.3.3" @@ -536,13 +635,13 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== +"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0", "@babel/helper-function-name@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" + integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" + "@babel/template" "^7.20.7" + "@babel/types" "^7.21.0" "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" @@ -551,12 +650,12 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-member-expression-to-functions@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz#a6f26e919582275a93c3aa6594756d71b0bb7f05" - integrity sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw== +"@babel/helper-member-expression-to-functions@^7.20.7", "@babel/helper-member-expression-to-functions@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz#319c6a940431a133897148515877d2f3269c3ba5" + integrity sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q== dependencies: - "@babel/types" "^7.20.7" + "@babel/types" "^7.21.0" "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6": version "7.18.6" @@ -565,10 +664,10 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.16.7", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" - integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg== +"@babel/helper-module-transforms@^7.16.7", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.0.tgz#89a8f86ad748870e3d024e470b2e8405e869db67" + integrity sha512-eD/JQ21IG2i1FraJnTMbUarAUkA7G988ofehG5MDCRXaUU91rEBJuCeSoou2Sk1y4RbLYXzqEg1QLwEmRU4qcQ== dependencies: "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-module-imports" "^7.18.6" @@ -576,8 +675,8 @@ "@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-validator-identifier" "^7.19.1" "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.10" - "@babel/types" "^7.20.7" + "@babel/traverse" "^7.21.0" + "@babel/types" "^7.21.0" "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" @@ -645,9 +744,9 @@ integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== "@babel/helper-validator-option@^7.16.7", "@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180" + integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ== "@babel/helper-wrap-function@^7.18.9": version "7.20.5" @@ -659,14 +758,14 @@ "@babel/traverse" "^7.20.5" "@babel/types" "^7.20.5" -"@babel/helpers@^7.16.7", "@babel/helpers@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.7.tgz#04502ff0feecc9f20ecfaad120a18f011a8e6dce" - integrity sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA== +"@babel/helpers@^7.16.7", "@babel/helpers@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.21.0.tgz#9dd184fb5599862037917cdc9eecb84577dc4e7e" + integrity sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA== dependencies: "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.7" - "@babel/types" "^7.20.7" + "@babel/traverse" "^7.21.0" + "@babel/types" "^7.21.0" "@babel/highlight@^7.18.6": version "7.18.6" @@ -677,10 +776,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.14.7", "@babel/parser@^7.16.12", "@babel/parser@^7.16.7", "@babel/parser@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.7.tgz#66fe23b3c8569220817d5feb8b9dcdc95bb4f71b" - integrity sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg== +"@babel/parser@^7.14.7", "@babel/parser@^7.16.12", "@babel/parser@^7.16.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.0": + version "7.21.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.1.tgz#a8f81ee2fe872af23faea4b17a08fcc869de7bcc" + integrity sha512-JzhBFpkuhBNYUY7qs+wTzNmyCWUHEaAFpQQD2YfU1rPL38/L43Wvid0fFkiOCnHvsGncRZgEPyGnltABLcVDTg== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": version "7.18.6" @@ -726,11 +825,11 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-proposal-class-static-block@^7.16.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.20.7.tgz#92592e9029b13b15be0f7ce6a7aedc2879ca45a7" - integrity sha512-AveGOoi9DAjUYYuUAG//Ig69GlazLnoyzMw68VCDux+c1tsnnH/OkYcpz/5xzMkEFC6UxjR5Gw1c+iY2wOGVeQ== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz#77bdd66fb7b605f3a61302d224bdfacf5547977d" + integrity sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.20.7" + "@babel/helper-create-class-features-plugin" "^7.21.0" "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-syntax-class-static-block" "^7.14.5" @@ -802,9 +901,9 @@ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-proposal-optional-chaining@^7.16.7", "@babel/plugin-proposal-optional-chaining@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.20.7.tgz#49f2b372519ab31728cc14115bb0998b15bfda55" - integrity sha512-T+A7b1kfjtRM51ssoOfS1+wbyCVqorfyZhT99TvxxLMirPShD8CzKMRepMlCBGM5RpHMbn8s+5MMHnPstJH6mQ== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea" + integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== dependencies: "@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" @@ -819,12 +918,12 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-proposal-private-property-in-object@^7.16.7": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz#309c7668f2263f1c711aa399b5a9a6291eef6135" - integrity sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz#19496bd9883dd83c23c7d7fc45dcd9ad02dfa1dc" + integrity sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-create-class-features-plugin" "^7.20.5" + "@babel/helper-create-class-features-plugin" "^7.21.0" "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" @@ -967,21 +1066,21 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-block-scoping@^7.16.7": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.11.tgz#9f5a3424bd112a3f32fe0cf9364fbb155cff262a" - integrity sha512-tA4N427a7fjf1P0/2I4ScsHGc5jcHPbb30xMbaTke2gxDuWpUfXDuX1FEymJwKk4tuGUvGcejAR6HdZVqmmPyw== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz#e737b91037e5186ee16b76e7ae093358a5634f02" + integrity sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ== dependencies: "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-transform-classes@^7.16.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.7.tgz#f438216f094f6bb31dc266ebfab8ff05aecad073" - integrity sha512-LWYbsiXTPKl+oBlXUGlwNlJZetXD5Am+CyBdqhPsDVjM9Jc8jwBJFrKhHf900Kfk2eZG1y9MAG3UNajol7A4VQ== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz#f469d0b07a4c5a7dbb21afad9e27e57b47031665" + integrity sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" "@babel/helper-compilation-targets" "^7.20.7" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" + "@babel/helper-function-name" "^7.21.0" "@babel/helper-optimise-call-expression" "^7.18.6" "@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-replace-supers" "^7.20.7" @@ -1027,11 +1126,11 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-for-of@^7.16.7": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" - integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz#964108c9988de1a60b4be2354a7d7e245f36e86e" + integrity sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-transform-function-name@^7.16.7": version "7.18.9" @@ -1297,6 +1396,11 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + "@babel/runtime@7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" @@ -1305,9 +1409,9 @@ regenerator-runtime "^0.13.4" "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.7.tgz#fcb41a5a70550e04a7b708037c7c32f7f356d8fd" - integrity sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ== + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" + integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== dependencies: regenerator-runtime "^0.13.11" @@ -1329,35 +1433,35 @@ "@babel/parser" "^7.20.7" "@babel/types" "^7.20.7" -"@babel/traverse@^7.16.10", "@babel/traverse@^7.20.10", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7": - version "7.20.12" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.12.tgz#7f0f787b3a67ca4475adef1f56cb94f6abd4a4b5" - integrity sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ== +"@babel/traverse@^7.16.10", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.0.tgz#0e1807abd5db98e6a19c204b80ed1e3f5bca0edc" + integrity sha512-Xdt2P1H4LKTO8ApPfnO1KmzYMFpp7D/EinoXzLYN/cHcBNrVCAkAtGUcXnHXrl/VGktureU6fkQrHSBE2URfoA== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.7" + "@babel/generator" "^7.21.0" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" + "@babel/helper-function-name" "^7.21.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" + "@babel/parser" "^7.21.0" + "@babel/types" "^7.21.0" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.4.4": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" - integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== +"@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.4.4": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.0.tgz#1da00d89c2f18b226c9207d96edbeb79316a1819" + integrity sha512-uR7NWq2VNFnDi7EYqiRz2Jv/VQIu38tu64Zy8TX2nQFQ6etJ9V/Rr2msW8BS132mum2rL645qpDrLtAJtVpuow== dependencies: "@babel/helper-string-parser" "^7.19.4" "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" "@capacitor/android@^4.0.0": - version "4.6.2" - resolved "https://registry.yarnpkg.com/@capacitor/android/-/android-4.6.2.tgz#2589525479a07c153f7ffd610684c3145c322aff" - integrity sha512-PQpOJnMi0i/d4UrT8bPdfkwlKAlQLgsyo2YKj+iUYjEIu8sKQvqDirLYnpeKhj4cflIG2u9mh/eFncooA+u2gw== + version "4.6.3" + resolved "https://registry.yarnpkg.com/@capacitor/android/-/android-4.6.3.tgz#36ecda8cc163d05de7336a5135926274054d6fee" + integrity sha512-jYND6OTsvIihxQiox6KARNKzlCHSGnMedXg5DGPZdREM+5F2SIvxBLQxC4/JpFBig2yJCVGsJMmhRkmz12S4FA== "@capacitor/app-launcher@^4.0.0": version "4.1.0" @@ -1397,9 +1501,9 @@ integrity sha512-lfUwDqZces3mQcBOyfxpBCsRWWSfLuPzekA1N3RaMgYVhD6/rdzFnzfRiksj1hm4It+lnULK0y+N5nxVnTt+0Q== "@capacitor/core@^4.0.0": - version "4.6.2" - resolved "https://registry.yarnpkg.com/@capacitor/core/-/core-4.6.2.tgz#9ea189218131ccf58f2b23fd3bdd69ed124dfe5b" - integrity sha512-M/KpAg+peft/HTb7svLiKHxjbll67ybs1vEqhZuvjXlwro53NxNXR4YJS7+wNXZSiA4Kxjtf+a754xGgZcMarA== + version "4.6.3" + resolved "https://registry.yarnpkg.com/@capacitor/core/-/core-4.6.3.tgz#70004316bce957ac5b5b3dd35dfdf170a09bbfb3" + integrity sha512-VJTUoZWUCVrp1cV1S4rqAwcV1/bF7KSVI4+/YUdVIBoHwnNxVweX15k5/etIeUZYaWxM6jwS2iIK9I86+G7ccQ== dependencies: tslib "^2.1.0" @@ -1409,26 +1513,29 @@ integrity sha512-ivko1RNK4hq63xhMacq8D6D97N5/SAafTsrmY/pghYrG6Cl2SEY0+IgRu7V9/VWeN3FSplyUPucjUTAFQxXN5g== "@capacitor/ios@^4.0.0": - version "4.6.2" - resolved "https://registry.yarnpkg.com/@capacitor/ios/-/ios-4.6.2.tgz#e0266a1998912b5e552c967c6053dc7c5d9d2851" - integrity sha512-3hQzbAOk+drCLyFjnytvkc20Mr077/9tQrv6iTghDXESDGR6EgcaYUXzKdVwuJscb0R459+5UQ2mYtkx6ES4TQ== + version "4.6.3" + resolved "https://registry.yarnpkg.com/@capacitor/ios/-/ios-4.6.3.tgz#3484006ac410ac33d1dd350a5adcab06a71b6933" + integrity sha512-sjvyIx/7U376YnTWIXjIBspzf0e1ZKocVjpTeqtM9AbUg4XtPQZa1Lje/lT6EFQ71bGTcxmq0wylnPRB7LzHNg== "@capacitor/splash-screen@^4.0.0": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@capacitor/splash-screen/-/splash-screen-4.1.3.tgz#3cf87e1c1095ac35a0d20495503605f396d73cb1" - integrity sha512-WkQQHFVK9kST+D8B0Z0jRGzZRQhtSKPhCkGez9dbOM+ggjCSjaXf90DK0nABbuNuO/99XAY6cJFkrZzw6erTBw== + version "4.1.4" + resolved "https://registry.yarnpkg.com/@capacitor/splash-screen/-/splash-screen-4.1.4.tgz#e73d678491175096386ecf3793acae9989643505" + integrity sha512-ETCxsJa94H4vYOXWLd0KKEmMwme4jrJddfieU0wXhhkRq3Fohv6CxTiG07vYbVzdMkzmWyq17yM5o3TKa3AQCA== "@capacitor/status-bar@^4.0.0": version "4.1.1" resolved "https://registry.yarnpkg.com/@capacitor/status-bar/-/status-bar-4.1.1.tgz#5b9a1acbe5efb30158e35be7a5ef7ffaaadaf804" integrity sha512-3wosxMD1XuIFz88+c2GdVEHSJV6u7suOeKQjyWf3zf9eFr622Sg+udZqDbC0dtTWXw97BWyCjv3r1EYJw7XnIA== -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" +"@capawesome/capacitor-file-picker@^0.5.8": + version "0.5.10" + resolved "https://registry.yarnpkg.com/@capawesome/capacitor-file-picker/-/capacitor-file-picker-0.5.10.tgz#ae9669fac6b5ea4d04cd2a5541a64bf7f5bd1e41" + integrity sha512-bm0rTOjeTGx1gYKz+6IfZAsC70z3Ss7BFMXXF18Gv5QlBJFbdD5oaJGSAJl1YHMVQlMvLAdTJd6hZ1SHIG1l0Q== + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== "@csstools/postcss-progressive-custom-properties@^1.1.0": version "1.3.0" @@ -1438,62 +1545,9 @@ postcss-value-parser "^4.2.0" "@csstools/selector-specificity@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz#1bfafe4b7ed0f3e4105837e056e0a89b108ebe36" - integrity sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg== - -"@dfinity/agent@^0.15.3": - version "0.15.3" - resolved "https://registry.yarnpkg.com/@dfinity/agent/-/agent-0.15.3.tgz#ea7061bcac38c75ecae281579e9934e0139b3d6d" - integrity sha512-yjJnAWI2CQY9kAFgavXU4TiKjb3NwaKUpu2LwCfgtJM4k6ofKlW+7q0tBJNs5WvHqRcKRDdn4d6yXKQi+ubS+w== - dependencies: - base64-arraybuffer "^0.2.0" - bignumber.js "^9.0.0" - borc "^2.1.1" - js-sha256 "0.9.0" - simple-cbor "^0.4.1" - ts-node "^10.8.2" - -"@dfinity/candid@^0.15.1": - version "0.15.3" - resolved "https://registry.yarnpkg.com/@dfinity/candid/-/candid-0.15.3.tgz#8a09660d12e16cee1a64cd684316844ebd76e678" - integrity sha512-jbfA+kr+gCrBuwxWm/j4Vpqzbnh9bsyUWu9CjopJis8xdxH3FIfNDWOzHZ/QaW7Co+6UoON1wzxMiy91/W5DQA== - dependencies: - ts-node "^10.8.2" - -"@dfinity/identity-secp256k1@^0.15.1": - version "0.15.3" - resolved "https://registry.yarnpkg.com/@dfinity/identity-secp256k1/-/identity-secp256k1-0.15.3.tgz#214c2d78c09e8db8d4f1ada0cc78818946deab91" - integrity sha512-JBdtwmw8EoQTxWR6fiN4Q0D1GJQMz0fvQSIwg8axgVkOcUSIhfPPtSSCWwJVyxfXZNU3OpEC0Kz44imbkEJKug== - dependencies: - "@dfinity/agent" "^0.15.3" - bip39 "^3.0.4" - bs58check "^2.1.2" - secp256k1 "^4.0.3" - -"@dfinity/nns@^0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@dfinity/nns/-/nns-0.10.0.tgz#d838ae126805f2c5d63ffe0188d208c42ed2f8ef" - integrity sha512-npBkb+s5wQIZbM6W+QX1AAvOL8QEk1CmunOKyT5w0av4RjnoDS5+25CHPhmNTWhLN0Xqx9HHjktOkk629SNkOQ== - dependencies: - crc "^4.1.1" - crc-32 "^1.2.2" - google-protobuf "^3.21.0" - js-sha256 "^0.9.0" - randombytes "^2.1.0" - -"@dfinity/principal@^0.15.1": - version "0.15.3" - resolved "https://registry.yarnpkg.com/@dfinity/principal/-/principal-0.15.3.tgz#53e65842dab09e97a04f6f6c70944de965172d89" - integrity sha512-XqHZVaJx/acmg6kFkF7PB156UwAquOS2WiAA753+nGKTG+TOC7OxbBXCr8vfEsd0mEzcmcLl+jLF8iUsC6Hk4w== - dependencies: - js-sha256 "^0.9.0" - ts-node "^10.8.2" - -"@dfinity/utils@^0.0.6": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@dfinity/utils/-/utils-0.0.6.tgz#8e105fdfb807dd1c12ab2016ecd3c4bfe5d4327b" - integrity sha512-lmLNbGfDE+6MX68qqtO+yy4IIqEvkhMNgiSFtij0HnhrtjJ0sQ/9mgFZR4auynwTQxqW97Zz4gKY56PPqyG6Gw== + version "2.1.1" + resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.1.1.tgz#c9c61d9fe5ca5ac664e1153bb0aa0eba1c6d6308" + integrity sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw== "@discoveryjs/json-ext@0.5.6": version "0.5.6" @@ -1677,12 +1731,12 @@ tslib "^2.1.0" "@ionic/core@^6.0.10": - version "6.5.0" - resolved "https://registry.yarnpkg.com/@ionic/core/-/core-6.5.0.tgz#60095211c15609218855a924117d65764db69334" - integrity sha512-vefrnd1WYZJnjSXwsY1sn3HJpBDKPGnwtO2US55Qrjz0d9HyUwocHgVvkvLAAKZG+LGErJbVeV8aTmdYEydRgg== + version "6.5.5" + resolved "https://registry.yarnpkg.com/@ionic/core/-/core-6.5.5.tgz#d7230efaa577957f4bbf363a723f9aa9ec56bbb6" + integrity sha512-2o755HOsbJS7IJtpBm7NN/Vl9mFFeu+gYlAerP6lYXw4EHemqITkRMdKDbMrB5eoMkU71ay9U5eV6KRbwzSqPQ== dependencies: "@stencil/core" "^2.18.0" - ionicons "^6.1.1" + ionicons "^6.1.3" tslib "^2.1.0" "@ionic/storage@2.2.0": @@ -1882,15 +1936,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== @@ -2160,6 +2206,21 @@ "@angular-devkit/schematics" "13.3.10" jsonc-parser "3.0.0" +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@socket.io/component-emitter@~3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" + integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== + +"@sovpro/delimited-stream@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@sovpro/delimited-stream/-/delimited-stream-1.1.0.tgz#4334bba7ee241036e580fdd99c019377630d26b4" + integrity sha512-kQpk267uxB19X3X2T1mvNMjyvIEonpNSHrMlK5ZaBU6aZxw7wPbpgKJOjHN3+/GPVpXgAV9soVT2oyHpLkLtyw== + "@stablelib/binary@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/binary/-/binary-1.0.1.tgz#c5900b94368baf00f811da5bdb1610963dfddf7f" @@ -2200,6 +2261,15 @@ resolved "https://registry.yarnpkg.com/@stablelib/hash/-/hash-1.0.1.tgz#3c944403ff2239fad8ebb9015e33e98444058bc5" integrity sha512-eTPJc/stDkdtOcrNMZ6mcMK1e6yBbqRBaNW55XA1jU8w/7QdnCF0CmMmOD1m7VSkBR44PWrMHU2l6r8YEQHMgg== +"@stablelib/hmac@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@stablelib/hmac/-/hmac-1.0.1.tgz#3d4c1b8cf194cb05d28155f0eed8a299620a07ec" + integrity sha512-V2APD9NSnhVpV/QMYgCVMIYKiYG6LSqw1S65wxVoirhU/51ACio6D4yDVSwMzuTJXWZoVHbDdINioBwKy5kVmA== + dependencies: + "@stablelib/constant-time" "^1.0.1" + "@stablelib/hash" "^1.0.1" + "@stablelib/wipe" "^1.0.1" + "@stablelib/int@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@stablelib/int/-/int-1.0.1.tgz#75928cc25d59d73d75ae361f02128588c15fd008" @@ -2286,15 +2356,22 @@ "@stablelib/wipe" "^1.0.1" "@stencil/core@^2.18.0": - version "2.22.1" - resolved "https://registry.yarnpkg.com/@stencil/core/-/core-2.22.1.tgz#dee491335024200abae8572661f78094a09973fe" - integrity sha512-L4EsWLXYkg24BfrR3aS1df3BSkH0RFyza+Tu84MaYoF2csiKTJxDTZuFHSnJeF8UdgzV7CBfnsIEV6r3s0+h3g== + version "2.22.2" + resolved "https://registry.yarnpkg.com/@stencil/core/-/core-2.22.2.tgz#f518b6bfae85352c72cd07fcaf2f2b61e0581fd9" + integrity sha512-r+vbxsGNcBaV1VDOYW25lv4QfXTlNoIb5GpUX7rZ+cr59yqYCZC5tlV+IzX6YgHKW62ulCc9M3RYtTfHtNbNNw== "@stencil/core@~2.13.0": version "2.13.0" resolved "https://registry.yarnpkg.com/@stencil/core/-/core-2.13.0.tgz#993fd74a5c7c8fe8af75848ca9df2211cd05b818" integrity sha512-EEKHOHgYpg3/iFUKMXTZJjUayRul7sXDwNw0OGgkEOe4t7JWiibDkzUHuruvpbqEydX+z1+ez5K2bMMY76c2wA== +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + "@taquito/local-forging@14.0.0": version "14.0.0" resolved "https://registry.yarnpkg.com/@taquito/local-forging/-/local-forging-14.0.0.tgz#6844d90fa530d39ce7aaaa8cd11c8723d494a7d9" @@ -2328,26 +2405,6 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== -"@tsconfig/node10@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" - integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" - integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== - "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.6": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" @@ -2399,11 +2456,35 @@ dependencies: "@types/node" "*" +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + "@types/cordova@latest": version "11.0.0" resolved "https://registry.yarnpkg.com/@types/cordova/-/cordova-11.0.0.tgz#9fba2d903ab7181ef0c0a43fb13659a6d02226b3" integrity sha512-AtBm1IAqqXsXszJe6XxuA2iXLhraNCj25p/FHRyikPeW0Z3YfgM6qzWb+VJglJTmZc5lqRNy84cYM/sQI5v6Vw== +"@types/core-js@^2.5.0": + version "2.5.5" + resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-2.5.5.tgz#dc5a013ee0b23bd5ac126403854fadabb4f24f75" + integrity sha512-C4vwOHrhsvxn7UFyk4NDQNUpgNKdWsT/bL39UWyD75KSEOObZSKa9mYDOCM5FGeJG2qtbG0XiEbUKND2+j0WOg== + +"@types/cors@^2.8.12": + version "2.8.13" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.13.tgz#b8ade22ba455a1b8cb3b5d3f35910fd204f84f94" + integrity sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA== + dependencies: + "@types/node" "*" + +"@types/debug@^4.1.4": + version "4.1.7" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" + integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== + dependencies: + "@types/ms" "*" + "@types/emscripten@^1.39.6": version "1.39.6" resolved "https://registry.yarnpkg.com/@types/emscripten/-/emscripten-1.39.6.tgz#698b90fe60d44acf93c31064218fbea93fbfd85a" @@ -2418,9 +2499,9 @@ "@types/estree" "*" "@types/eslint@*": - version "8.4.10" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.10.tgz#19731b9685c19ed1552da7052b6f668ed7eb64bb" - integrity sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw== + version "8.21.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.21.1.tgz#110b441a210d53ab47795124dbc3e9bb993d1e7c" + integrity sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -2435,22 +2516,22 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== -"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.31": - version "4.17.32" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.32.tgz#93dda387f5516af616d8d3f05f2c4c79d81e1b82" - integrity sha512-aI5h/VOkxOF2Z1saPy0Zsxs5avets/iaiAJYznQFm5By/pamU31xWKL//epiF4OfUA2qTOc9PV6tCUjhO8wlZA== +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": + version "4.17.33" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz#de35d30a9d637dc1450ad18dd583d75d5733d543" + integrity sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" "@types/express@*": - version "4.17.15" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.15.tgz#9290e983ec8b054b65a5abccb610411953d417ff" - integrity sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ== + version "4.17.17" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" + integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== dependencies: "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.31" + "@types/express-serve-static-core" "^4.17.33" "@types/qs" "*" "@types/serve-static" "*" @@ -2468,6 +2549,23 @@ dependencies: "@types/node" "*" +"@types/jasmine@*": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-4.3.1.tgz#2d8ab5601c2fe7d9673dcb157e03f128ab5c5fff" + integrity sha512-Vu8l+UGcshYmV1VWwULgnV/2RDbBaO6i2Ptx7nd//oJPIZGhoI1YLST4VKagD2Pq/Bc2/7zvtvhM7F3p4SN7kQ== + +"@types/jasmine@~2.8.8": + version "2.8.19" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.8.19.tgz#88318fcc0f68d543214bf95325a443221f27bd8b" + integrity sha512-LD9nOC/+6AHfEFKpOW3Nu7wmXHEs41BWOr9uyaXYHx/iiLPAEfBZ2AlIH3yk+xyLWi5I83fLltMiDCrrHvU3Wg== + +"@types/jasminewd2@~2.0.3": + version "2.0.10" + resolved "https://registry.yarnpkg.com/@types/jasminewd2/-/jasminewd2-2.0.10.tgz#ae31c237aa6421bde30f1058b1d20f4577e54443" + integrity sha512-J7mDz7ovjwjc+Y9rR9rY53hFWKATcIkrr9DwQWmOas4/pnIPJTXawnzjwpHm3RSxz/e3ZVUvQ7cRbd5UQLo10g== + dependencies: + "@types/jasmine" "*" + "@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -2483,10 +2581,15 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== -"@types/node@*", "@types/node@>=13.7.0": - version "18.11.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" - integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== +"@types/ms@*": + version "0.7.31" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" + integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== + +"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=13.7.0": + version "18.14.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.0.tgz#94c47b9217bbac49d4a67a967fdcdeed89ebb7d0" + integrity sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A== "@types/node@10.12.18": version "10.12.18" @@ -2515,6 +2618,11 @@ dependencies: "@types/node" "*" +"@types/q@^0.0.32": + version "0.0.32" + resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5" + integrity sha512-qYi3YV9inU/REEfxwVcGZzbS3KG/Xs90lv0Pr+lDtuVjBPGd1A+eciXzVSaRvLify132BfcvhvEjeVahrUl0Ug== + "@types/qs@*": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" @@ -2537,6 +2645,11 @@ dependencies: "@types/node" "*" +"@types/selenium-webdriver@^3.0.0": + version "3.0.20" + resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.20.tgz#448771a0608ebf1c86cb5885914da6311e323c3a" + integrity sha512-6d8Q5fqS9DWOXEhMDiF6/2FjyHdmP/jSTAUyeQR7QwrFeNmYyzmvGxD5aLIHL445HjWgibs0eAig+KPnbaesXA== + "@types/serve-index@^1.9.1": version "1.9.1" resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" @@ -2571,6 +2684,13 @@ dependencies: "@types/node" "*" +"@types/yauzl@^2.9.1": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599" + integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw== + dependencies: + "@types/node" "*" + "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -2780,7 +2900,7 @@ acorn-walk@^7.0.0: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn-walk@^8.1.1, acorn-walk@^8.2.0: +acorn-walk@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== @@ -2791,9 +2911,9 @@ acorn@^7.0.0: integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.0: - version "8.8.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" - integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== adjust-sourcemap-loader@^4.0.0: version "4.0.0" @@ -2803,6 +2923,11 @@ adjust-sourcemap-loader@^4.0.0: loader-utils "^2.0.0" regex-parser "^2.2.11" +adm-zip@^0.5.2: + version "0.5.10" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.10.tgz#4a51d5ab544b1f5ce51e1b9043139b639afff45b" + integrity sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ== + agent-base@6, agent-base@^6.0.0, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -2810,6 +2935,13 @@ agent-base@6, agent-base@^6.0.0, agent-base@^6.0.2: dependencies: debug "4" +agent-base@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + agentkeepalive@^4.1.3, agentkeepalive@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717" @@ -2834,7 +2966,7 @@ ajv-formats@2.1.1, ajv-formats@^2.1.1: dependencies: ajv "^8.0.0" -ajv-keywords@^3.5.2: +ajv-keywords@^3.4.0, ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== @@ -2856,7 +2988,7 @@ ajv@8.9.0: require-from-string "^2.0.2" uri-js "^4.2.2" -ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.9.2: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2889,6 +3021,13 @@ angularx-qrcode@^11.0.0: qrcode "1.4.2" tslib "^2.0.0" +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -2913,6 +3052,16 @@ ansi-html-community@^0.0.8: resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== + ansi-regex@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" @@ -2928,6 +3077,11 @@ ansi-regex@^6.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -2955,6 +3109,46 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +app-builder-bin@2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-2.7.1.tgz#9f690af65093821b8a6149aa29ce9f8c81fc554c" + integrity sha512-ubIBeiL9XysjMW4HETBKxj3DC8ika6dGyC0vftPc0kZwGh1iXQ5bycsjoAqY/3t3BBEEIg0VruicvBaUl1pOSQ== + +app-builder-lib@20.44.4, app-builder-lib@~20.44.4: + version "20.44.4" + resolved "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-20.44.4.tgz#39ac20b3155e1b0c2499862bcdea879b50389573" + integrity sha512-1K1xfrhyqDgnibwyuYMgvfwGilGLMF31YwOUJ8IXreyjRef9lUjWW+BZuBXqk4Uqd0C0EYPjhofgpuN0WoAQ+A== + dependencies: + "7zip-bin" "~4.1.0" + app-builder-bin "2.7.1" + async-exit-hook "^2.0.1" + bluebird-lst "^1.0.9" + builder-util "10.1.2" + builder-util-runtime "8.2.5" + chromium-pickle-js "^0.2.0" + debug "^4.1.1" + ejs "^2.6.2" + electron-osx-sign "0.4.11" + electron-publish "20.44.4" + fs-extra-p "^8.0.2" + hosted-git-info "^2.7.1" + is-ci "^2.0.0" + isbinaryfile "^4.0.1" + js-yaml "^3.13.1" + lazy-val "^1.0.4" + minimatch "^3.0.4" + normalize-package-data "^2.5.0" + plist "^3.0.1" + read-config-file "3.2.2" + sanitize-filename "^1.6.1" + semver "^6.1.1" + temp-file "^3.3.3" + +app-root-path@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a" + integrity sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA== + "aproba@^1.0.3 || ^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" @@ -2980,6 +3174,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +array-differ@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-2.1.0.tgz#4b9c1c3f14b906757082925769e8ab904f4801b1" + integrity sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w== + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -2990,6 +3189,13 @@ array-flatten@^2.1.0: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== +array-union@^1.0.1, array-union@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng== + dependencies: + array-uniq "^1.0.1" + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" @@ -3000,6 +3206,16 @@ array-union@^3.0.1: resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== + +arrify@^1.0.0, arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + asn1.js@^5.2.0: version "5.4.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" @@ -3010,6 +3226,18 @@ asn1.js@^5.2.0: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + assert@^1.4.0: version "1.5.0" resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" @@ -3040,6 +3268,11 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +async-exit-hook@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3" + integrity sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw== + async@^2.6.4: version "2.6.4" resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" @@ -3079,6 +3312,16 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== + axios@^0.24.0: version "0.24.0" resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" @@ -3155,21 +3398,33 @@ base58check@^2.0.0: dependencies: bs58 "^3.0.0" -base64-arraybuffer@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz#4b944fac0191aa5907afe2d8c999ccc57ce80f45" - integrity sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ== +base64-arraybuffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc" + integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ== base64-js@^1.0.2, base64-js@^1.2.0, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +base64id@2.0.0, base64id@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" + integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== + batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + bech32@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" @@ -3271,7 +3526,7 @@ bl@^1.0.0: readable-stream "^2.3.5" safe-buffer "^5.1.1" -bl@^4.1.0: +bl@^4.0.3, bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== @@ -3285,6 +3540,25 @@ blakejs@^1.1.0, blakejs@^1.2.1: resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.2.1.tgz#5057e4206eadb4a97f7c0b6e197a505042fc3814" integrity sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ== +blocking-proxy@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/blocking-proxy/-/blocking-proxy-1.0.1.tgz#81d6fd1fe13a4c0d6957df7f91b75e98dac40cb2" + integrity sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA== + dependencies: + minimist "^1.2.0" + +bluebird-lst@^1.0.7, bluebird-lst@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/bluebird-lst/-/bluebird-lst-1.0.9.tgz#a64a0e4365658b9ab5fe875eb9dfb694189bb41c" + integrity sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw== + dependencies: + bluebird "^3.5.5" + +bluebird@^3.5.0, bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -3313,6 +3587,24 @@ body-parser@1.20.1: type-is "~1.6.18" unpipe "1.0.0" +body-parser@^1.19.0: + version "1.20.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" + bonjour@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" @@ -3330,19 +3622,33 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -borc@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/borc/-/borc-2.1.2.tgz#6ce75e7da5ce711b963755117dd1b187f6f8cf19" - integrity sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w== +borc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/borc/-/borc-3.0.0.tgz#49ada1be84de86f57bb1bb89789f34c186dfa4fe" + integrity sha512-ec4JmVC46kE0+layfnwM3l15O70MlFiEbmQHY/vpqIKiUtPVntv4BY4NVnz3N4vb21edV3mY97XVckFvYHWF9g== dependencies: bignumber.js "^9.0.0" - buffer "^5.5.0" + buffer "^6.0.3" commander "^2.15.0" ieee754 "^1.1.13" - iso-url "~0.4.7" - json-text-sequence "~0.1.0" + iso-url "^1.1.5" + json-text-sequence "~0.3.0" readable-stream "^3.6.0" +boxen@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-3.2.0.tgz#fbdff0de93636ab4450886b6ff45b92d098f45eb" + integrity sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^2.4.2" + cli-boxes "^2.2.0" + string-width "^3.0.0" + term-size "^1.2.0" + type-fest "^0.3.0" + widest-line "^2.0.0" + bplist-parser@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.2.tgz#3ac79d67ec52c4c107893e0237eb787cbacbced7" @@ -3511,15 +3817,22 @@ browserify@^17.0.0: vm-browserify "^1.0.0" xtend "^4.0.0" -browserslist@^4.14.5, browserslist@^4.19.1, browserslist@^4.21.3, browserslist@^4.21.4, browserslist@^4.9.1: - version "4.21.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" - integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== +browserslist@^4.14.5, browserslist@^4.19.1, browserslist@^4.21.3, browserslist@^4.21.4, browserslist@^4.21.5, browserslist@^4.9.1: + version "4.21.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" + integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== + dependencies: + caniuse-lite "^1.0.30001449" + electron-to-chromium "^1.4.284" + node-releases "^2.0.8" + update-browserslist-db "^1.0.10" + +browserstack@^1.5.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.6.1.tgz#e051f9733ec3b507659f395c7a4765a1b1e358b3" + integrity sha512-GxtFjpIaKdbAyzHfFDKixKO8IBT7wR3NjbzrGc78nNs/Ciys9wU3/nBtsqsWv5nDSrdI5tz0peKuzCPuNXNUiw== dependencies: - caniuse-lite "^1.0.30001400" - electron-to-chromium "^1.4.251" - node-releases "^2.0.6" - update-browserslist-db "^1.0.9" + https-proxy-agent "^2.2.1" bs58@^3.0.0: version "3.1.0" @@ -3606,6 +3919,48 @@ buffer@~5.2.1: base64-js "^1.0.2" ieee754 "^1.1.4" +builder-util-runtime@8.2.5: + version "8.2.5" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.2.5.tgz#6f19330178345f8ce2c65842b0a9cf6a187d5946" + integrity sha512-YILT+YUlxrE3yNB6mDC1tF+Q24mr1LSYdjP5U861jbBeDZfvy1/VPDzW3boMVrDtzYnDnvkYrzLJnoh6TXA75w== + dependencies: + bluebird-lst "^1.0.9" + debug "^4.1.1" + fs-extra-p "^8.0.2" + sax "^1.2.4" + +builder-util-runtime@^8.2.5: + version "8.9.2" + resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz#a9669ae5b5dcabfe411ded26678e7ae997246c28" + integrity sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A== + dependencies: + debug "^4.3.2" + sax "^1.2.4" + +builder-util@10.1.2, builder-util@~10.1.2: + version "10.1.2" + resolved "https://registry.yarnpkg.com/builder-util/-/builder-util-10.1.2.tgz#29e631025aa4c837411d5e4ef425d14e320eb2d0" + integrity sha512-LQMh36Cg0r4ZfKqNlaUclndS/IXxZ3OdCgmXvw1vdP3QwYT2NkyE7LfMikAFIHpXOs6zsVH+iW+Fe/AX1jfFag== + dependencies: + "7zip-bin" "~4.1.0" + "@types/debug" "^4.1.4" + app-builder-bin "2.7.1" + bluebird-lst "^1.0.9" + builder-util-runtime "^8.2.5" + chalk "^2.4.2" + debug "^4.1.1" + fs-extra-p "^8.0.2" + is-ci "^2.0.0" + js-yaml "^3.13.1" + source-map-support "^0.5.12" + stat-mode "^0.3.0" + temp-file "^3.3.3" + +builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + integrity sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ== + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -3674,6 +4029,19 @@ cacache@^16.1.0: tar "^6.1.11" unique-filename "^2.0.0" +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.1.0.tgz#865576dfef39c0d6a7defde794d078f5308e3ef3" @@ -3697,10 +4065,15 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-lite@^1.0.30001299, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426: - version "1.0.30001446" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001446.tgz#6d4ba828ab19f49f9bcd14a8430d30feebf1e0c5" - integrity sha512-fEoga4PrImGcwUUGEol/PoFCSBnSkA9drgdkxXkJLsUBOnJ8rs3zDv6ApqYXGQFOyMPsjh79naWhF4DAxbF8rw== +caniuse-lite@^1.0.30001299, caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001449: + version "1.0.30001457" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz#6af34bb5d720074e2099432aa522c21555a18301" + integrity sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== caw@^2.0.0: version "2.0.1" @@ -3717,7 +4090,7 @@ cbor-sync@^1.0.4: resolved "https://registry.yarnpkg.com/cbor-sync/-/cbor-sync-1.0.4.tgz#5a11a1ab75c2a14d1af1b237fd84aa8c1593662f" integrity sha512-GWlXN4wiz0vdWWXBU71Dvc1q3aBo0HytqwAZnXF1wOwjqNnDWA1vZ1gDMFLlqohak31VQzmhiYfiCX5QSSfagA== -chalk@2.4.2, chalk@^2.0.0: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3726,6 +4099,17 @@ chalk@2.4.2, chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + chalk@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" @@ -3747,7 +4131,7 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -"chokidar@>=3.0.0 <4.0.0", chokidar@^3.0.0, chokidar@^3.5.2: +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.0.0, chokidar@^3.5.1, chokidar@^3.5.2: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -3762,6 +4146,11 @@ chardet@^0.7.0: optionalDependencies: fsevents "~2.3.2" +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + chownr@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" @@ -3772,8 +4161,18 @@ chrome-trace-event@^1.0.2: resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" +chromium-pickle-js@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205" + integrity sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: @@ -3790,6 +4189,11 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-boxes@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -3825,6 +4229,15 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -3843,11 +4256,30 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" +clone-response@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== + dependencies: + mimic-response "^1.0.0" + clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== +codelyzer@~4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-4.5.0.tgz#a65ddeeeca2894653253a89bfa229118ff9f59b1" + integrity sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ== + dependencies: + app-root-path "^2.1.0" + css-selector-tokenizer "^0.7.0" + cssauron "^1.4.0" + semver-dsl "^1.0.1" + source-map "^0.5.7" + sprintf-js "^1.1.1" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -3862,6 +4294,11 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" +color-convert@~0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd" + integrity sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling== + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" @@ -3882,7 +4319,7 @@ colorette@^2.0.10: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== -colors@^1.1.2: +colors@1.4.0, colors@^1.1.2: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== @@ -3897,14 +4334,14 @@ combine-source-map@^0.8.0, combine-source-map@~0.8.0: lodash.memoize "~3.0.3" source-map "~0.5.3" -combined-stream@^1.0.8: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" -commander@^2.15.0, commander@^2.20.0, commander@^2.8.1: +commander@^2.12.1, commander@^2.15.0, commander@^2.20.0, commander@^2.8.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -3919,6 +4356,11 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== +compare-version@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/compare-version/-/compare-version-0.1.2.tgz#0162ec2d9351f5ddd59a9202cba935366a725080" + integrity sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A== + component-emitter@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -3967,11 +4409,33 @@ config-chain@^1.1.11: ini "^1.3.4" proto-list "~1.2.1" +configstore@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7" + integrity sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ== + dependencies: + dot-prop "^4.1.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + connect-history-api-fallback@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== +connect@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" @@ -3994,10 +4458,10 @@ content-disposition@0.5.4, content-disposition@^0.5.2: dependencies: safe-buffer "5.2.1" -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +content-type@~1.0.4, content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== convert-source-map@^1.5.1, convert-source-map@^1.7.0: version "1.9.0" @@ -4019,6 +4483,11 @@ cookie@0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +cookie@~0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + cookiejar@^2.1.2: version "2.1.4" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" @@ -4088,11 +4557,11 @@ cordova.plugins.diagnostic@4.0.10: minimist "1.2.0" core-js-compat@^3.20.2, core-js-compat@^3.21.0: - version "3.27.2" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.27.2.tgz#607c50ad6db8fd8326af0b2883ebb987be3786da" - integrity sha512-welaYuF7ZtbYKGrIy7y3eb40d37rG1FvzEOfe7hSLd2iD6duMDqUhRfSvCGyC46HhR6Y8JXXdZ2lnRUMkPBpvg== + version "3.28.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.28.0.tgz#c08456d854608a7264530a2afa281fadf20ecee6" + integrity sha512-myzPgE7QodMg4nnd3K1TDoES/nADRStM8Gpz0D6nhkwbmwEnE0ZGJgoWsvQ722FR8D7xS0n0LV556RcEicjTyg== dependencies: - browserslist "^4.21.4" + browserslist "^4.21.5" core-js@3.20.3: version "3.20.3" @@ -4100,15 +4569,28 @@ core-js@3.20.3: integrity sha512-vVl8j8ph6tRS3B8qir40H7yw7voy17xL0piAjlbBUsH7WIfzoedL/ZOr1OV9FyZQLWXsayOJyV4tnRyXR85/ag== core-js@^3.10.1: - version "3.27.2" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.27.2.tgz#85b35453a424abdcacb97474797815f4d62ebbf7" - integrity sha512-9ashVQskuh5AZEZ1JdQWp1GqSoC1e1G87MzRqg2gIfVAQ7Qn9K+uFj8EcniUFA4P2NLZfV+TOlX1SzoKfo+s7w== + version "3.28.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.28.0.tgz#ed8b9e99c273879fdfff0edfc77ee709a5800e4a" + integrity sha512-GiZn9D4Z/rSYvTeg1ljAIsEqFm0LaN9gVtwDCrKL80zHtS31p9BAjmTxVqTQDMpwlMolJZOFntUG2uwyj7DAqw== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +cors@~2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + cosmiconfig@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" @@ -4120,11 +4602,16 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -crc-32@^1.2.0, crc-32@^1.2.2: +crc-32@1.2.2, crc-32@^1.2.0: version "1.2.2" resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== +crc@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/crc/-/crc-4.3.2.tgz#49b7821cbf2cf61dfd079ed93863bbebd5469b9a" + integrity sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A== + crc@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" @@ -4132,11 +4619,6 @@ crc@^3.8.0: dependencies: buffer "^5.1.0" -crc@^4.1.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/crc/-/crc-4.3.2.tgz#49b7821cbf2cf61dfd079ed93863bbebd5469b9a" - integrity sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A== - create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -4192,6 +4674,15 @@ cross-fetch@^3.1.5: dependencies: node-fetch "2.6.7" +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A== + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + cross-spawn@^7.0.0, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -4218,6 +4709,11 @@ crypto-browserify@3.12.0, crypto-browserify@^3.0.0: randombytes "^2.0.0" randomfill "^1.0.3" +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + integrity sha512-GsVpkFPlycH7/fRR7Dhcmnoii54gV1nz7y4CWyeFS14N+JVBBhY+r8amRHE4BwSYal7BPTDp8isvAlCxyFt3Hg== + css-blank-pseudo@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz#36523b01c12a25d812df343a32c322d2a2324561" @@ -4262,6 +4758,14 @@ css-select@^4.2.0: domutils "^2.8.0" nth-check "^2.0.1" +css-selector-tokenizer@^0.7.0: + version "0.7.3" + resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz#735f26186e67c749aaf275783405cf0661fae8f1" + integrity sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg== + dependencies: + cssesc "^3.0.0" + fastparse "^1.1.2" + css-what@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" @@ -4276,6 +4780,13 @@ css@^3.0.0: source-map "^0.6.1" source-map-resolve "^0.6.0" +cssauron@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/cssauron/-/cssauron-1.4.0.tgz#a6602dff7e04a8306dc0db9a551e92e8b5662ad8" + integrity sha512-Ht70DcFBh+/ekjVrYS2PlDMdSQEl3OFNmjK6lcn49HptBgilXf/Zwg4uFh9Xn0pX3Q8YOkSjIFOfK2osvdqpBw== + dependencies: + through X.X.X + cssdb@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-5.1.0.tgz#ec728d5f5c0811debd0820cbebda505d43003400" @@ -4286,30 +4797,54 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +custom-event@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" + integrity sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg== + dash-ast@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dash-ast/-/dash-ast-1.0.0.tgz#12029ba5fb2f8aa6f0a861795b23c1b4b6c27d37" integrity sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA== +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + data-uri-to-buffer@3: version "3.0.1" resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== -debug@2.6.9, debug@^2.1.0: +date-format@^4.0.14: + version "4.0.14" + resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" + integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== + +debug@2.6.9, debug@^2.1.0, debug@^2.6.8: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" +debug@4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + debug@4.3.3: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" @@ -4317,7 +4852,7 @@ debug@4.3.3: dependencies: ms "2.1.2" -debug@^3.2.6, debug@^3.2.7: +debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -4334,7 +4869,7 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== -decompress-response@^3.2.0: +decompress-response@^3.2.0, decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== @@ -4406,6 +4941,11 @@ deep-equal@^1.0.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -4425,15 +4965,20 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== define-properties@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== dependencies: has-property-descriptors "^1.0.0" object-keys "^1.1.1" @@ -4453,6 +4998,19 @@ degenerator@^3.0.2: esprima "^4.0.0" vm2 "^3.9.8" +del@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + integrity sha512-Z4fzpbIRjOu7lO5jCETSWoqUDVe0IPOlfugBsF6suen2LKDlVb4QZpKEM9P+buNJ4KI1eN7I083w/pbKUpsrWQ== + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + del@^6.0.0: version "6.1.1" resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a" @@ -4477,11 +5035,6 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== -delimit-stream@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/delimit-stream/-/delimit-stream-0.1.0.tgz#9b8319477c0e5f8aeb3ce357ae305fc25ea1cd2b" - integrity sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ== - depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -4534,6 +5087,16 @@ detective@^5.2.0: defined "^1.0.0" minimist "^1.2.6" +devtools-protocol@0.0.901419: + version "0.0.901419" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.901419.tgz#79b5459c48fe7e1c5563c02bd72f8fec3e0cebcd" + integrity sha512-4INMPwNm9XRpBukhNbF7OB6fNTTCaI8pzy/fXg0xQzAy5h3zL1P8xT3QazgKqBrb/hAYwIBizqDBZ7GtJE74QQ== + +di@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" + integrity sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA== + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -4560,6 +5123,20 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +dmg-builder@6.7.2: + version "6.7.2" + resolved "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-6.7.2.tgz#4ba4955e7f35f159ce53c68d74d3ea74875f9afd" + integrity sha512-xfYOwhHjOSOIqkk8A0h8zcaio/WyzrAWpMTu9hzV3Z5PI4tOG0Pq6a9Lh/mHr1r3bydif8R21qGvKU1Re9CpUg== + dependencies: + app-builder-lib "~20.44.4" + bluebird-lst "^1.0.9" + builder-util "~10.1.2" + fs-extra-p "^8.0.2" + iconv-lite "^0.4.24" + js-yaml "^3.13.1" + parse-color "^1.0.0" + sanitize-filename "^1.6.1" + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -4580,6 +5157,16 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" +dom-serialize@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" + integrity sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ== + dependencies: + custom-event "~1.0.0" + ent "~2.2.0" + extend "^3.0.0" + void-elements "^2.0.0" + dom-serializer@^1.0.1: version "1.4.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" @@ -4615,6 +5202,23 @@ domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" +dot-prop@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" + integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ== + dependencies: + is-obj "^1.0.0" + +dotenv-expand@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-4.2.0.tgz#def1f1ca5d6059d24a766e587942c21106ce1275" + integrity sha512-pHWVt6L/YkqbBCMb1hG6e7oO0WdMhlapDIibl+BZ9PncVE3i+G77uvNr8GUxW2ItSituOK8QOYC9oOJjwWD94A== + +dotenv@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" + integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== + download@^6.2.5: version "6.2.5" resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714" @@ -4644,15 +5248,72 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.251: - version "1.4.284" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" - integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== +ejs@^2.6.2: + version "2.7.4" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" + integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== + +electron-builder@^20.43.0: + version "20.44.4" + resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-20.44.4.tgz#c47981ddf486d582c0ae0f4d530c831010aacad7" + integrity sha512-H8zzP01albkKh2Ec1zc0A7RGriUkHb5M99NJskaYtgKtGATTAGH+r9OIWVk5Hk9c1dLMVudbqEeaSlygMF2asw== + dependencies: + app-builder-lib "20.44.4" + bluebird-lst "^1.0.9" + builder-util "10.1.2" + builder-util-runtime "8.2.5" + chalk "^2.4.2" + dmg-builder "6.7.2" + fs-extra-p "^8.0.2" + is-ci "^2.0.0" + lazy-val "^1.0.4" + read-config-file "3.2.2" + sanitize-filename "^1.6.1" + update-notifier "^3.0.0" + yargs "^13.2.4" + +electron-osx-sign@0.4.11: + version "0.4.11" + resolved "https://registry.yarnpkg.com/electron-osx-sign/-/electron-osx-sign-0.4.11.tgz#8377732fe7b207969f264b67582ee47029ce092f" + integrity sha512-VVd40nrnVqymvFrY9ZkOYgHJOvexHHYTR3di/SN+mjJ0OWhR1I8BRVj3U+Yamw6hnkZZNKZp52rqL5EFAAPFkQ== + dependencies: + bluebird "^3.5.0" + compare-version "^0.1.2" + debug "^2.6.8" + isbinaryfile "^3.0.2" + minimist "^1.2.0" + plist "^3.0.1" + +electron-publish@20.44.4: + version "20.44.4" + resolved "https://registry.yarnpkg.com/electron-publish/-/electron-publish-20.44.4.tgz#f826de3788c4e3848b7f6ebd2c3acb910a1d66cc" + integrity sha512-50NzsKOnNqOpGJzPl04vMyitdguUvp15FWKWtu4KISsHfgdLMWGgxHGZwfMphc/vf364zXvPHsYQza3MASgaEQ== + dependencies: + bluebird-lst "^1.0.9" + builder-util "~10.1.2" + builder-util-runtime "^8.2.5" + chalk "^2.4.2" + fs-extra-p "^8.0.2" + lazy-val "^1.0.4" + mime "^2.4.4" + +electron-to-chromium@^1.4.284: + version "1.4.305" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.305.tgz#e4dfe3e06ab783f33171f9bde9e8ed092510fcd0" + integrity sha512-WETy6tG0CT5gm1O+xCbyapWNsCcmIvrn4NHViIGYo2AT8FV2qUCXdaB+WqYxSv/vS5mFqhBYnfZAAkVArjBmUg== elementtree@^0.1.6, elementtree@^0.1.7: version "0.1.7" @@ -4701,13 +5362,34 @@ encoding@^0.1.12, encoding@^0.1.13: dependencies: iconv-lite "^0.6.2" -end-of-stream@^1.0.0, end-of-stream@^1.1.0: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" +engine.io-parser@~5.0.3: + version "5.0.6" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.6.tgz#7811244af173e157295dec9b2718dfe42a64ef45" + integrity sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw== + +engine.io@~6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.4.1.tgz#8056b4526a88e779f9c280d820422d4e3eeaaae5" + integrity sha512-JFYQurD/nbsA5BSPmbaOSLa3tSVj8L6o4srSwXXY3NqE+gGUNmmPTbhn8tjzcCtSqhFgIeqef81ngny8JM25hw== + dependencies: + "@types/cookie" "^0.4.1" + "@types/cors" "^2.8.12" + "@types/node" ">=10.0.0" + accepts "~1.3.4" + base64id "2.0.0" + cookie "~0.4.1" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~5.0.3" + ws "~8.11.0" + enhanced-resolve@^5.8.3: version "5.12.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" @@ -4716,6 +5398,11 @@ enhanced-resolve@^5.8.3: graceful-fs "^4.2.4" tapable "^2.2.0" +ent@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + integrity sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA== + entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -4755,6 +5442,18 @@ es6-object-assign@^1.1.0: resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" integrity sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw== +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== + dependencies: + es6-promise "^4.0.3" + esbuild-android-arm64@0.14.22: version "0.14.22" resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.22.tgz#fb051169a63307d958aec85ad596cfc7d7770303" @@ -4907,6 +5606,14 @@ escodegen@^1.8.1: optionalDependencies: source-map "~0.6.1" +eslint-plugin-prettier@^2.2.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.7.0.tgz#b4312dcf2c1d965379d7f9d5b5f8aaadc6a45904" + integrity sha512-CStQYJgALoQBw3FsBzH0VOVDRnJ/ZimUlpLm226U8qgqYJfPOY/CPK6wyRInMxh73HSKg5wyRwdS4BVYYHwokA== + dependencies: + fast-diff "^1.1.1" + jest-docblock "^21.0.0" + eslint-scope@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -5031,6 +5738,32 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw== + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" + integrity sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA== + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + execa@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" @@ -5061,6 +5794,11 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + express@^4.17.1: version "4.18.2" resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" @@ -5113,7 +5851,7 @@ ext-name@^5.0.0: ext-list "^2.0.0" sort-keys-length "^1.0.0" -extend@3.0.2: +extend@3.0.2, extend@^3.0.0, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -5132,6 +5870,27 @@ extract-files@^9.0.0: resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== +extract-zip@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + fancy-log@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" @@ -5147,6 +5906,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-diff@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-glob@^3.2.7, fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" @@ -5173,6 +5937,11 @@ fast-safe-stringify@^2.0.7: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== +fastparse@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" + integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== + fastq@^1.6.0: version "1.15.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" @@ -5247,6 +6016,19 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + finalhandler@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" @@ -5269,6 +6051,13 @@ find-cache-dir@^3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -5284,6 +6073,11 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +flatted@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + follow-redirects@^1.0.0, follow-redirects@^1.14.4: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" @@ -5296,6 +6090,11 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -5305,6 +6104,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + formidable@^1.2.2: version "1.2.6" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.6.tgz#d2a51d60162bbc9b4a055d8457a7c75315d1a168" @@ -5330,6 +6138,40 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== +fs-extra-p@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra-p/-/fs-extra-p-7.0.1.tgz#4eec0b6dfa150fa90f6ddd773b4fb1d55cad54e3" + integrity sha512-yhd2OV0HnHt2oitlp+X9hl2ReX4X/7kQeL7/72qzPHTZj5eUPGzAKOvEglU02Fa1OeG2rSy/aKB4WGVaLiF8tw== + dependencies: + bluebird-lst "^1.0.7" + fs-extra "^7.0.1" + +fs-extra-p@^8.0.2: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra-p/-/fs-extra-p-8.1.0.tgz#781b7105e96cf3c1d3c8a88a83215c8a31c52bae" + integrity sha512-sCLpU5kk5CvrWZvFM9dUlqPgHrE02AEt6XYzF7kDscr5COc7DHfhNfODTXt0bkVNmt5DkvU2uJSYjorxY3bRKA== + dependencies: + bluebird-lst "^1.0.9" + fs-extra "^8.1.0" + +fs-extra@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -5419,9 +6261,9 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== dependencies: function-bind "^1.1.1" has "^1.0.3" @@ -5452,7 +6294,14 @@ get-stream@^3.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ== -get-stream@^5.0.0: +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -5476,6 +6325,13 @@ get-uri@3: fs-extra "^8.1.0" ftp "^0.3.10" +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -5507,7 +6363,7 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.0.3, glob@^7.0.6, glob@^7.1.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -5530,6 +6386,13 @@ glob@^8.0.1: minimatch "^5.0.1" once "^1.3.0" +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + integrity sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg== + dependencies: + ini "^1.3.4" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -5559,10 +6422,17 @@ globby@^12.0.2: merge2 "^1.4.1" slash "^4.0.0" -google-protobuf@^3.21.0: - version "3.21.2" - resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.2.tgz#4580a2bea8bbb291ee579d1fefb14d6fa3070ea4" - integrity sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA== +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + integrity sha512-HJRTIH2EeH44ka+LWig+EqT2ONSYpVlNfx6pyd592/VF1TbfljJ7elwie7oSwcViLGqOdWocSdu2txwBF9bjmQ== + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" gopd@^1.0.1: version "1.0.1" @@ -5591,7 +6461,24 @@ got@^7.0.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -graceful-fs@^4.1.10, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -5616,6 +6503,26 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -5662,6 +6569,11 @@ has-unicode@^2.0.1: resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + has@^1.0.0, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -5719,7 +6631,7 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hosted-git-info@^2.1.4: +hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== @@ -5746,15 +6658,20 @@ html-entities@^2.3.2: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + htmlescape@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" integrity sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg== -http-cache-semantics@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== http-deceiver@^1.2.7: version "1.2.7" @@ -5825,6 +6742,15 @@ http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" @@ -5846,6 +6772,14 @@ https-proxy-agent@5.0.0: agent-base "6" debug "4" +https-proxy-agent@^2.2.1: + version "2.2.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" + integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" @@ -5863,6 +6797,11 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +husky@^7.0.0: + version "7.0.4" + resolved "https://registry.yarnpkg.com/husky/-/husky-7.0.4.tgz#242048245dc49c8fb1bf0cc7cfb98dd722531535" + integrity sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ== + iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -5894,6 +6833,11 @@ ignore-walk@^4.0.1: dependencies: minimatch "^3.0.4" +ignore@^3.3.7: + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== + ignore@^5.1.9, ignore@^5.2.0: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" @@ -5910,9 +6854,9 @@ immediate@~3.0.5: integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== immutable@^4.0.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.2.tgz#2da9ff4384a4330c36d4d1bc88e90f9e0b0ccd16" - integrity sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og== + version "4.2.4" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.4.tgz#83260d50889526b4b531a5e293709a77f7c55a2a" + integrity sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w== import-fresh@^3.2.1: version "3.3.0" @@ -5922,6 +6866,11 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -5965,7 +6914,7 @@ ini@2.0.0: resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== -ini@^1.3.4: +ini@^1.3.4, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -6037,10 +6986,10 @@ insert-module-globals@^7.2.1: undeclared-identifiers "^1.1.2" xtend "^4.0.0" -ionicons@^6.0.0, ionicons@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/ionicons/-/ionicons-6.1.1.tgz#4c24c29aaf9ec235d741e7fe692e47ea814b1a7d" - integrity sha512-Qe6mx25DFNwA9UL1rhewI5StI3uD4+BqB2KdvLjyWhtvoUXwyAsmfHLZuDANAHQowIKtTt6BZCt5/g5NIQ635Q== +ionicons@^6.0.0, ionicons@^6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/ionicons/-/ionicons-6.1.3.tgz#32ce7dd0ed00bb71a9df612501745ad0d2e5d2df" + integrity sha512-ptzz38dd/Yq+PgjhXegh7yhb/SLIk1bvL9vQDtLv1aoSc7alO6mX2DIMgcKYzt9vrNWkRu1f9Jr78zIFFyOXqw== dependencies: "@stencil/core" "^2.18.0" @@ -6099,6 +7048,13 @@ is-callable@^1.1.3: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + is-core-module@^2.8.1, is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" @@ -6152,6 +7108,14 @@ is-hex-prefixed@1.0.0: resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" integrity sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA== +is-installed-globally@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + integrity sha512-ERNhMg+i/XgDwPIPF3u24qpajVreaiSuvpb1Uu0jugw7KKcxGyCX8cgp8P5fwTmAuXku6beDHHECdKArjlg7tw== + dependencies: + global-dirs "^0.1.0" + is-path-inside "^1.0.0" + is-interactive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" @@ -6175,21 +7139,50 @@ is-natural-number@^4.0.1: resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" integrity sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ== +is-npm@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-3.0.0.tgz#ec9147bfb629c43f494cf67936a961edec7e8053" + integrity sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== + is-object@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + integrity sha512-cnS56eR9SPAscL77ik76ATVqoPARTqPIVkMDVxRaWH06zT+6+CzIroYRJ0VVvm0Z1zfAvxvz9i/D3Ppjaqt5Nw== + is-path-cwd@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== +is-path-in-cwd@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" + integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ== + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + integrity sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g== + dependencies: + path-is-inside "^1.0.1" + is-path-inside@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" @@ -6246,7 +7239,7 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.3: gopd "^1.0.1" has-tostringtag "^1.0.0" -is-typedarray@^1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== @@ -6268,6 +7261,11 @@ is-wsl@^2.1.1, is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -6283,15 +7281,27 @@ isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== +isbinaryfile@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80" + integrity sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw== + dependencies: + buffer-alloc "^1.2.0" + +isbinaryfile@^4.0.1, isbinaryfile@^4.0.8: + version "4.0.10" + resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" + integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -iso-url@~0.4.7: - version "0.4.7" - resolved "https://registry.yarnpkg.com/iso-url/-/iso-url-0.4.7.tgz#de7e48120dae46921079fe78f325ac9e9217a385" - integrity sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog== +iso-url@^1.1.5: + version "1.2.1" + resolved "https://registry.yarnpkg.com/iso-url/-/iso-url-1.2.1.tgz#db96a49d8d9a64a1c889fc07cc525d093afb1811" + integrity sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng== isobject@^3.0.1: version "3.0.1" @@ -6306,12 +7316,17 @@ isomorphic-fetch@^3.0.0: node-fetch "^2.6.1" whatwg-fetch "^3.4.1" -istanbul-lib-coverage@^3.2.0: +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== -istanbul-lib-instrument@^5.0.4: +istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: version "5.2.1" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== @@ -6322,6 +7337,32 @@ istanbul-lib-instrument@^5.0.4: istanbul-lib-coverage "^3.2.0" semver "^6.3.0" +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + isurl@^1.0.0-alpha5: version "1.0.0" resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" @@ -6330,6 +7371,47 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" +jasmine-core@^3.6.0: + version "3.99.1" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.99.1.tgz#5bfa4b2d76618868bfac4c8ff08bb26fffa4120d" + integrity sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg== + +jasmine-core@~2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.8.0.tgz#bcc979ae1f9fd05701e45e52e65d3a5d63f1a24e" + integrity sha512-SNkOkS+/jMZvLhuSx1fjhcNWUC/KG6oVyFUGkSBEr9n1axSNduWU8GlI7suaHXr4yxjet6KjrUZxUTE5WzzWwQ== + +jasmine-core@~3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.9.0.tgz#09a3c8169fe98ec69440476d04a0e4cb4d59e452" + integrity sha512-Tv3kVbPCGVrjsnHBZ38NsPU3sDOtNa0XmbG2baiyJqdb5/SPpDO6GVwJYtUryl6KB4q1Ssckwg612ES9Z0dreQ== + +jasmine-spec-reporter@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/jasmine-spec-reporter/-/jasmine-spec-reporter-7.0.0.tgz#94b939448e63d4e2bd01668142389f20f0a8ea49" + integrity sha512-OtC7JRasiTcjsaCBPtMO0Tl8glCejM4J4/dNuOJdA8lBjz4PmWjYQ6pzb0uzpBNAWJMDudYuj9OdXJWqM2QTJg== + dependencies: + colors "1.4.0" + +jasmine@2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.8.0.tgz#6b089c0a11576b1f16df11b80146d91d4e8b8a3e" + integrity sha512-KbdGQTf5jbZgltoHs31XGiChAPumMSY64OZMWLNYnEnMfG5uwGBhffePwuskexjT+/Jea/gU3qAU8344hNohSw== + dependencies: + exit "^0.1.2" + glob "^7.0.6" + jasmine-core "~2.8.0" + +jasminewd2@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e" + integrity sha512-Rn0nZe4rfDhzA63Al3ZGh0E+JTmM6ESZYXJGKuqKGZObsAB9fwXPD03GjtIEvJBDOhN94T5MzbwZSqzFHSQPzg== + +jest-docblock@^21.0.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" + integrity sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw== + jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" @@ -6339,12 +7421,12 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" -jetifier@1.6.6: - version "1.6.6" - resolved "https://registry.yarnpkg.com/jetifier/-/jetifier-1.6.6.tgz#fec8bff76121444c12dc38d2dad6767c421dab68" - integrity sha512-JNAkmPeB/GS2tCRqUzRPsTOHpGDah7xP18vGJfIjZC+W2sxEHbxgJxetIjIqhjQ3yYbYNEELkM/spKLtwoOSUQ== +jetifier@^1.6.6: + version "1.6.8" + resolved "https://registry.yarnpkg.com/jetifier/-/jetifier-1.6.8.tgz#e88068697875cbda98c32472902c4d3756247798" + integrity sha512-3Zi16h6L5tXDRQJTb221cnRoVG9/9OvreLdLU2/ZjRv/GILL+2Cemt0IKvkowwkDpvouAU1DQPOJ7qaiHeIdrw== -js-sha256@0.9.0, js-sha256@^0.9.0: +js-sha256@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== @@ -6359,7 +7441,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.1: +js-yaml@^3.12.1, js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -6372,6 +7454,11 @@ jsbi@^3.1.5: resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.2.5.tgz#b37bb90e0e5c2814c1c2a1bcd8c729888a2e37d6" integrity sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ== +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -6382,6 +7469,11 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== + json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -6402,12 +7494,22 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-text-sequence@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.1.1.tgz#a72f217dc4afc4629fff5feb304dc1bd51a2f3d2" - integrity sha512-L3mEegEWHRekSHjc7+sc8eJhba9Clq1PZ8kMkzf8OxElhXc8O4TS5MwcVlj9aEbm5dr81N90WHC5nAz3UO971w== +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json-text-sequence@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.3.0.tgz#6603e0ee45da41f949669fd18744b97fb209e6ce" + integrity sha512-7khKIYPKwXQem4lWXfpIN/FEnhztCeRPSxH4qm3fVlqulwujrRDD54xAwDDn/qVKpFtV550+QAkcWJcufzqQuA== dependencies: - delimit-stream "0.1.0" + "@sovpro/delimited-stream" "^1.1.0" json5@^1.0.1: version "1.0.2" @@ -6416,7 +7518,7 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -json5@^2.1.2, json5@^2.2.2: +json5@^2.1.0, json5@^2.1.2, json5@^2.2.2: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -6452,6 +7554,57 @@ jsonparse@^1.2.0, jsonparse@^1.3.1: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +jszip@^3.1.3: + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + setimmediate "^1.0.5" + +karma-chrome-launcher@~3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz#baca9cc071b1562a1db241827257bfe5cab597ea" + integrity sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ== + dependencies: + which "^1.2.1" + +karma-coverage@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/karma-coverage/-/karma-coverage-2.2.0.tgz#64f838b66b71327802e7f6f6c39d569b7024e40c" + integrity sha512-gPVdoZBNDZ08UCzdMHHhEImKrw1+PAOQOIiffv1YsvxFhBjqvo/SVXNk4tqn1SYqX0BJZT6S/59zgxiBe+9OuA== + dependencies: + istanbul-lib-coverage "^3.2.0" + istanbul-lib-instrument "^5.1.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.1" + istanbul-reports "^3.0.5" + minimatch "^3.0.4" + +karma-jasmine-html-reporter@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz#52c489a74d760934a1089bfa5ea4a8fcb84cc28b" + integrity sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ== + +karma-jasmine@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-4.0.2.tgz#386db2a3e1acc0af5265c711f673f78f1e4938de" + integrity sha512-ggi84RMNQffSDmWSyyt4zxzh2CQGwsxvYYsprgyR1j8ikzIduEdOlcLvXjZGwXG/0j41KUXOWsUCBfbEHPWP9g== + dependencies: + jasmine-core "^3.6.0" + karma-source-map-support@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz#58526ceccf7e8730e56effd97a4de8d712ac0d6b" @@ -6459,6 +7612,43 @@ karma-source-map-support@1.4.0: dependencies: source-map-support "^0.5.5" +karma-spec-reporter@0.0.32: + version "0.0.32" + resolved "https://registry.yarnpkg.com/karma-spec-reporter/-/karma-spec-reporter-0.0.32.tgz#2e9c7207ea726771260259f82becb543209e440a" + integrity sha512-ZXsYERZJMTNRR2F3QN11OWF5kgnT/K2dzhM+oY3CDyMrDI3TjIWqYGG7c15rR9wjmy9lvdC+CCshqn3YZqnNrA== + dependencies: + colors "^1.1.2" + +karma@~6.3.4: + version "6.3.20" + resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.20.tgz#12f5c3b0e68f204607cb0a3a78d4751b42ef61a8" + integrity sha512-HRNQhMuKOwKpjYlWiJP0DUrJOh+QjaI/DTaD8b9rEm4Il3tJ8MijutVZH4ts10LuUFst/CedwTS6vieCN8yTSw== + dependencies: + "@colors/colors" "1.5.0" + body-parser "^1.19.0" + braces "^3.0.2" + chokidar "^3.5.1" + connect "^3.7.0" + di "^0.0.1" + dom-serialize "^2.2.1" + glob "^7.1.7" + graceful-fs "^4.2.6" + http-proxy "^1.18.1" + isbinaryfile "^4.0.8" + lodash "^4.17.21" + log4js "^6.4.1" + mime "^2.5.2" + minimatch "^3.0.4" + mkdirp "^0.5.5" + qjobs "^1.2.0" + range-parser "^1.2.1" + rimraf "^3.0.2" + socket.io "^4.4.1" + source-map "^0.6.1" + tmp "^0.2.1" + ua-parser-js "^0.7.30" + yargs "^16.1.1" + keccak@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" @@ -6468,6 +7658,13 @@ keccak@^3.0.0: node-gyp-build "^4.2.0" readable-stream "^3.6.0" +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -6496,6 +7693,18 @@ labeled-stream-splicer@^2.0.0: inherits "^2.0.1" stream-splicer "^2.0.0" +latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + +lazy-val@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.5.tgz#6cf3b9f5bc31cee7ee3e369c0832b7583dcd923d" + integrity sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q== + leek@0.0.24: version "0.0.24" resolved "https://registry.yarnpkg.com/leek/-/leek-0.0.24.tgz#e400e57f0e60d8ef2bd4d068dc428a54345dbcda" @@ -6551,6 +7760,13 @@ lie@3.1.1: dependencies: immediate "~3.0.5" +lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + lifehash@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/lifehash/-/lifehash-0.0.2.tgz#ac0b211603e54b87f6cf1ca552b1304f3a4b5fe9" @@ -6629,6 +7845,14 @@ localforage@>=1.5.0: dependencies: lie "3.1.1" +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -6747,6 +7971,17 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" +log4js@^6.4.1: + version "6.8.0" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.8.0.tgz#f0fe9b2b82725aaf97f20692e23381a5c5722448" + integrity sha512-g+V8gZyurIexrOvWQ+AcZsIvuK/lBnx2argejZxL4gVZ4Hq02kUYH6WZOnqxgBml+zzQZYdaEoTN84B6Hzm8Fg== + dependencies: + date-format "^4.0.14" + debug "^4.3.4" + flatted "^3.2.7" + rfdc "^1.3.0" + streamroller "^3.1.5" + long@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" @@ -6757,11 +7992,24 @@ long@^5.2.0: resolved "https://registry.yarnpkg.com/long/-/long-5.2.1.tgz#e27595d0083d103d2fa2c20c7699f8e0c92b897f" integrity sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A== -lowercase-keys@^1.0.0: +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -6777,9 +8025,9 @@ lru-cache@^6.0.0: yallist "^4.0.0" lru-cache@^7.7.1: - version "7.14.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.14.1.tgz#8da8d2f5f59827edb388e63e459ac23d6d408fea" - integrity sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA== + version "7.17.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.17.0.tgz#00c7ba5919e5ea7c69ff94ddabbf32cb09ab805c" + integrity sha512-zSxlVVwOabhVyTi6E8gYv2cr6bXK+8ifYz5/uyJb9feXX6NACVDwY4p5Ut3WC3Ivo/QhpARHU3iujx2xGAYHbQ== macos-release@^2.5.0: version "2.5.0" @@ -6815,7 +8063,7 @@ make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.2, make-dir@^3.1.0: +make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -6938,7 +8186,7 @@ mime-db@1.52.0, "mime-db@>= 1.43.0 < 2", mime-db@^1.28.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -6950,7 +8198,7 @@ mime@1.6.0, mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.4.6: +mime@^2.4.4, mime@^2.4.6, mime@^2.5.2: version "2.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== @@ -6960,7 +8208,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-response@^1.0.0: +mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== @@ -7009,9 +8257,9 @@ minimist@1.2.0: integrity sha512-7Wl+Jz+IGWuSdgsQEJ4JunV0si/iMhg42MnQQG6h1R6TNeVenp4U9x5CC5v/gYqz/fENLQITAWXidNtVL0NNbw== minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.6: - version "1.2.7" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" - integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== minipass-collect@^1.0.2: version "1.0.2" @@ -7079,11 +8327,9 @@ minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3, minipass@^3. yallist "^4.0.0" minipass@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.0.0.tgz#7cebb0f9fa7d56f0c5b17853cbe28838a8dbbd3b" - integrity sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw== - dependencies: - yallist "^4.0.0" + version "4.2.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.0.tgz#4bf124d8c87c14e99846f9a27c3219d956998c0e" + integrity sha512-ExlilAIS7zJ2EWUMaVXi14H+FnZ18kr17kFkGemMqBx6jW0m8P6XfqwYVPEG53ENlgsED+alVP9ZxC3JzkK23Q== minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" @@ -7098,7 +8344,7 @@ mkdirp-classic@^0.5.2: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@^0.5.6: +mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@^0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -7136,6 +8382,11 @@ moment@^2.24.0, moment@^2.27.0: resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== +mri@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -7164,6 +8415,16 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" +multimatch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-3.0.0.tgz#0e2534cc6bc238d9ab67e1b9cd5fcd85a6dbf70b" + integrity sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA== + dependencies: + array-differ "^2.0.3" + array-union "^1.0.2" + arrify "^1.0.1" + minimatch "^3.0.4" + mute-stream@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -7255,6 +8516,11 @@ node-addon-api@^5.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -7295,10 +8561,10 @@ node-gyp@^8.2.0: tar "^6.1.2" which "^2.0.2" -node-releases@^2.0.6: - version "2.0.8" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.8.tgz#0f349cdc8fcfa39a92ac0be9bc48b7706292b9ae" - integrity sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A== +node-releases@^2.0.8: + version "2.0.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" + integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== nopt@^5.0.0: version "5.0.0" @@ -7307,7 +8573,7 @@ nopt@^5.0.0: dependencies: abbrev "1" -normalize-package-data@^2.3.2: +normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -7327,6 +8593,11 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + npm-bundled@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" @@ -7395,6 +8666,13 @@ npm-registry-fetch@^12.0.0: minizlib "^2.1.2" npm-package-arg "^8.1.5" +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== + dependencies: + path-key "^2.0.0" + npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -7419,7 +8697,12 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" -object-assign@^4.0.1, object-assign@^4.1.1: +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -7454,6 +8737,13 @@ on-finished@2.4.1: dependencies: ee-first "1.1.1" +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + on-headers@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" @@ -7473,7 +8763,7 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -open@8.4.0, open@^8.0.9: +open@8.4.0: version "8.4.0" resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== @@ -7490,6 +8780,15 @@ open@^7.0.4, open@^7.4.2: is-docker "^2.0.0" is-wsl "^2.1.1" +open@^8.0.9: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -7530,7 +8829,7 @@ os-name@^4.0.0: macos-release "^2.5.0" windows-release "^4.0.0" -os-tmpdir@~1.0.2: +os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== @@ -7540,6 +8839,11 @@ p-cancelable@^0.3.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + p-event@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-event/-/p-event-1.3.0.tgz#8e6b4f4f65c72bc5b6fe28b75eda874f96a4a085" @@ -7552,6 +8856,13 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -7559,6 +8870,13 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -7595,6 +8913,11 @@ p-timeout@^1.1.1: dependencies: p-finally "^1.0.0" +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -7624,6 +8947,16 @@ pac-resolver@^5.0.0: ip "^1.1.5" netmask "^2.0.2" +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + pacote@12.0.3: version "12.0.3" resolved "https://registry.yarnpkg.com/pacote/-/pacote-12.0.3.tgz#b6f25868deb810e7e0ddf001be88da2bcaca57c7" @@ -7649,7 +8982,7 @@ pacote@12.0.3: ssri "^8.0.1" tar "^6.1.0" -pako@^1.0.3, pako@~1.0.5: +pako@^1.0.3, pako@~1.0.2, pako@~1.0.5: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== @@ -7679,6 +9012,13 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-color@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-color/-/parse-color-1.0.0.tgz#7b748b95a83f03f16a94f535e52d7f3d94658619" + integrity sha512-fuDHYgFHJGbpGMgw9skY/bj3HL/Jrn4l/5rSspy00DoT4RyLnDcRvPxdZ+r6OFwIsgAuhDh4I09tAId4mI12bw== + dependencies: + color-convert "~0.5.0" + parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" @@ -7753,6 +9093,16 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== + +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" @@ -7801,6 +9151,11 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -7849,14 +9204,14 @@ piscina@3.2.0: optionalDependencies: nice-napi "^1.0.2" -pkg-dir@^4.1.0: +pkg-dir@4.2.0, pkg-dir@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" -plist@^3.0.2, plist@^3.0.6: +plist@^3.0.1, plist@^3.0.2, plist@^3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.6.tgz#7cfb68a856a7834bca6dbfe3218eb9c7740145d3" integrity sha512-WiIVYyrp8TD4w8yCvyeIr+lkmrGRd5u0VbRnU+tP/aRLxP/YadJUYOMZJ/6hIa3oUyVCsycXvtNRgd5XBJIbiA== @@ -8175,11 +9530,33 @@ prepend-http@^1.0.1: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg== +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== + +prettier@2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" + integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== + pretty-bytes@^5.3.0: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== +pretty-quick@^1.11.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-1.11.1.tgz#462ffa2b93d24c05b7a0c3a001e08601a0c55ee4" + integrity sha512-kSXCkcETfak7EQXz6WOkCeCqpbC4GIzrN/vaneTGMP/fAtD8NerA9bPhCUqHAks1geo7biZNl5uEMPceeneLuA== + dependencies: + chalk "^2.3.0" + execa "^0.8.0" + find-up "^2.1.0" + ignore "^3.3.7" + mri "^1.1.0" + multimatch "^3.0.0" + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -8190,6 +9567,11 @@ process@0.11.10, process@~0.11.0: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== +progress@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.1.tgz#c9242169342b1c29d275889c95734621b1952e31" + integrity sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg== + progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -8240,6 +9622,27 @@ protobufjs@^6.11.2: "@types/node" ">=13.7.0" long "^4.0.0" +protractor@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/protractor/-/protractor-7.0.0.tgz#c3e263608bd72e2c2dc802b11a772711a4792d03" + integrity sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw== + dependencies: + "@types/q" "^0.0.32" + "@types/selenium-webdriver" "^3.0.0" + blocking-proxy "^1.0.0" + browserstack "^1.5.1" + chalk "^1.1.3" + glob "^7.0.3" + jasmine "2.8.0" + jasminewd2 "^2.1.0" + q "1.4.1" + saucelabs "^1.5.0" + selenium-webdriver "3.6.0" + source-map-support "~0.4.0" + webdriver-js-extender "2.1.0" + webdriver-manager "^12.1.7" + yargs "^15.3.1" + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -8262,7 +9665,7 @@ proxy-agent@^5.0.0: proxy-from-env "^1.0.0" socks-proxy-agent "^5.0.0" -proxy-from-env@^1.0.0: +proxy-from-env@1.1.0, proxy-from-env@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== @@ -8272,6 +9675,16 @@ prr@~1.0.1: resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + +psl@^1.1.28: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" @@ -8302,10 +9715,28 @@ punycode@^1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== -punycode@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.2.0.tgz#2092cc57cd2582c38e4e7e8bb869dc8d3148bc74" - integrity sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw== +punycode@^2.1.0, punycode@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +puppeteer@^10.2.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-10.4.0.tgz#a6465ff97fda0576c4ac29601406f67e6fea3dc7" + integrity sha512-2cP8mBoqnu5gzAVpbZ0fRaobBWZM8GEUF4I1F6WbgHrKV/rz7SX8PG2wMymZgD0wo0UBlg2FBPNxlF/xlqW6+w== + dependencies: + debug "4.3.1" + devtools-protocol "0.0.901419" + extract-zip "2.0.1" + https-proxy-agent "5.0.0" + node-fetch "2.6.1" + pkg-dir "4.2.0" + progress "2.0.1" + proxy-from-env "1.1.0" + rimraf "3.0.2" + tar-fs "2.0.0" + unbzip2-stream "1.3.3" + ws "7.4.6" pushdata-bitcoin@^1.0.1: version "1.0.1" @@ -8314,6 +9745,21 @@ pushdata-bitcoin@^1.0.1: dependencies: bitcoin-ops "^1.3.0" +q@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" + integrity sha512-/CdEdaw49VZVmyIDGUQKDDT53c7qBkO6g5CefWz91Ae+l4+cRtcDYwMTXh6me4O8TMldeGHG3N2Bl84V78Ywbg== + +q@^1.4.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== + +qjobs@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" + integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== + qrcode-reader@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/qrcode-reader/-/qrcode-reader-1.0.4.tgz#95d9bb9e8130800361a96cb5a43124ad1d9e06b8" @@ -8336,6 +9782,11 @@ qs@6.11.0, qs@^6.9.4: dependencies: side-channel "^1.0.4" +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + querystring-es3@~0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -8371,7 +9822,7 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.5.1, raw-body@^2.2.0: +raw-body@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== @@ -8381,6 +9832,26 @@ raw-body@2.5.1, raw-body@^2.2.0: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@2.5.2, raw-body@^2.2.0: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +rc@1.2.8, rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + read-cache@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" @@ -8388,6 +9859,21 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" +read-config-file@3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/read-config-file/-/read-config-file-3.2.2.tgz#57bbff7dd97caf237d0d625bd541c6d0efb4d067" + integrity sha512-PuFpMgZF01VB0ydH1dfitAxCP/fh+qnfbA9cYNIPoxPbz0SMngsrafCtaHDWfER7MwlDz4fmrNBhPkakxxFpTg== + dependencies: + ajv "^6.9.2" + ajv-keywords "^3.4.0" + bluebird-lst "^1.0.7" + dotenv "^6.2.0" + dotenv-expand "^4.2.0" + fs-extra-p "^7.0.1" + js-yaml "^3.12.1" + json5 "^2.1.0" + lazy-val "^1.0.4" + read-only-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0" @@ -8422,7 +9908,7 @@ readable-stream@1.1.x: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.6, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: +readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -8499,22 +9985,31 @@ regexp.prototype.flags@^1.2.0: define-properties "^1.1.3" functions-have-names "^1.2.2" -regexpu-core@^5.2.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc" - integrity sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw== +regexpu-core@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.1.tgz#66900860f88def39a5cb79ebd9490e84f17bcdfb" + integrity sha512-nCOzW2V/X15XpLsK2rlgdwrysrBq+AauCn+omItIz4R1pIcmeot5zvjdmOBRLzEH/CkC6IxMJVmxDe3QcMuNVQ== dependencies: + "@babel/regjsgen" "^0.8.0" regenerate "^1.4.2" regenerate-unicode-properties "^10.1.0" - regjsgen "^0.7.1" regjsparser "^0.9.1" unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.1.0" -regjsgen@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" - integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== +registry-auth-token@^4.0.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" + integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== + dependencies: + rc "1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" regjsparser@^0.9.1: version "0.9.1" @@ -8532,6 +10027,32 @@ replace@1.2.1: minimatch "3.0.4" yargs "^15.3.1" +request@^2.87.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -8582,7 +10103,7 @@ resolve@1.22.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.1.4, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.4.0: +resolve@^1.1.4, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.4.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -8591,6 +10112,13 @@ resolve@^1.1.4, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.17. path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== + dependencies: + lowercase-keys "^1.0.0" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -8614,13 +10142,25 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^3.0.0, rimraf@^3.0.2: +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + +rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" +rimraf@^2.2.8, rimraf@^2.5.2, rimraf@^2.5.4: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -8677,11 +10217,18 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0, safer-buffer@^2.1.2: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sanitize-filename@^1.6.1: + version "1.6.3" + resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378" + integrity sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg== + dependencies: + truncate-utf8-bytes "^1.0.0" + sass-loader@12.4.0: version "12.4.0" resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.4.0.tgz#260b0d51a8a373bb8e88efc11f6ba5583fea0bcf" @@ -8699,6 +10246,13 @@ sass@1.49.0: immutable "^4.0.0" source-map-js ">=0.6.2 <2.0.0" +saucelabs@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/saucelabs/-/saucelabs-1.5.0.tgz#9405a73c360d449b232839919a86c396d379fd9d" + integrity sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ== + dependencies: + https-proxy-agent "^2.2.1" + sax@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.4.tgz#74b6d33c9ae1e001510f179a91168588f1aedaa9" @@ -8747,7 +10301,7 @@ sdp@^1.5.0: resolved "https://registry.yarnpkg.com/sdp/-/sdp-1.5.4.tgz#8e038f6ddb14bd765ae1f4b5216e12094511e0d0" integrity sha512-9x0+fpJHW2bbqtIktmL+H9m+BswgurPVPhWrur4cCZPDWDSsdGYvRBaKhDXlnNCD1b/Xi8cOTG2u703CTQuwgg== -secp256k1@^4.0.0, secp256k1@^4.0.1, secp256k1@^4.0.3: +secp256k1@^4.0.0, secp256k1@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== @@ -8782,6 +10336,16 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== +selenium-webdriver@3.6.0, selenium-webdriver@^3.0.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz#2ba87a1662c020b8988c981ae62cb2a01298eafc" + integrity sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q== + dependencies: + jszip "^3.1.3" + rimraf "^2.5.4" + tmp "0.0.30" + xml2js "^0.4.17" + selfsigned@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" @@ -8789,7 +10353,21 @@ selfsigned@^2.0.0: dependencies: node-forge "^1" -"semver@2 || 3 || 4 || 5", semver@^5.6.0: +semver-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + integrity sha512-gL8F8L4ORwsS0+iQ34yCYv///jsOq0ZL7WP55d1HnJ32o7tyFYEFQZQA22mrLIacZdU6xecaBBZ+uEiffGNyXw== + dependencies: + semver "^5.0.3" + +semver-dsl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/semver-dsl/-/semver-dsl-1.0.1.tgz#d3678de5555e8a61f629eed025366ae5f27340a0" + integrity sha512-e8BOaTo007E3dMuQQTnPdalbKTABKNS7UxoBIDnwOqRa+QwMrCPjynB8zAlPF6xlqUfdLPPLIJ13hJNmhtq8Ng== + dependencies: + semver "^5.3.0" + +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -8801,7 +10379,7 @@ semver@7.3.5: dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -8904,6 +10482,13 @@ shasum-object@^1.0.0: dependencies: fast-safe-stringify "^2.0.7" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -8911,15 +10496,20 @@ shebang-command@^2.0.0: dependencies: shebang-regex "^3.0.0" +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.6.1: - version "1.7.4" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" - integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== + version "1.8.0" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.0.tgz#20d078d0eaf71d54f43bd2ba14a1b5b9bfa5c8ba" + integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ== side-channel@^1.0.4: version "1.0.4" @@ -8930,7 +10520,7 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -8979,6 +10569,33 @@ smart-buffer@^4.2.0: resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== +socket.io-adapter@~2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12" + integrity sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA== + dependencies: + ws "~8.11.0" + +socket.io-parser@~4.2.1: + version "4.2.2" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.2.tgz#1dd384019e25b7a3d374877f492ab34f2ad0d206" + integrity sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + +socket.io@^4.4.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.6.1.tgz#62ec117e5fce0692fa50498da9347cfb52c3bc70" + integrity sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA== + dependencies: + accepts "~1.3.4" + base64id "~2.0.0" + debug "~4.3.2" + engine.io "~6.4.1" + socket.io-adapter "~2.5.2" + socket.io-parser "~4.2.1" + sockjs@^0.3.21: version "0.3.24" resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" @@ -9074,7 +10691,7 @@ source-map-resolve@^0.6.0: atob "^2.1.2" decode-uri-component "^0.2.0" -source-map-support@0.5.21, source-map-support@^0.5.5, source-map-support@~0.5.20: +source-map-support@0.5.21, source-map-support@^0.5.12, source-map-support@^0.5.17, source-map-support@^0.5.5, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -9082,6 +10699,13 @@ source-map-support@0.5.21, source-map-support@^0.5.5, source-map-support@~0.5.20 buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@~0.4.0: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -9092,7 +10716,7 @@ source-map@0.7.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== -source-map@^0.5.0, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== @@ -9168,6 +10792,11 @@ split2@^4.1.0: resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809" integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ== +sprintf-js@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" + integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -9178,6 +10807,21 @@ ssh-config@^1.1.1: resolved "https://registry.yarnpkg.com/ssh-config/-/ssh-config-1.1.6.tgz#c6ce2d7f85f395178c9e47c448d62b8adf9b2523" integrity sha512-ZPO9rECxzs5JIQ6G/2EfL1I9ho/BVZkx9HRKn8+0af7QgwAmumQ7XBFP1ggMyPMo+/tUbmv0HFdv4qifdO/9JA== +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + ssri@^8.0.0, ssri@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" @@ -9192,12 +10836,17 @@ ssri@^9.0.0: dependencies: minipass "^3.1.1" +stat-mode@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.3.0.tgz#69283b081f851582b328d2a4ace5f591ce52f54b" + integrity sha512-QjMLR0A3WwFY2aZdV0okfFEJB5TRjkggXZjxP3A1RsWsNHNu3YPv8btmtc6iCFZ0Rul3FE93OYogvhOUClU+ng== + statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -"statuses@>= 1.4.0 < 2": +"statuses@>= 1.4.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== @@ -9236,6 +10885,15 @@ stream-splicer@^2.0.0: inherits "^2.0.1" readable-stream "^2.0.2" +streamroller@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.5.tgz#1263182329a45def1ffaef58d31b15d13d2ee7ff" + integrity sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw== + dependencies: + date-format "^4.0.14" + debug "^4.3.4" + fs-extra "^8.1.0" + "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -9245,6 +10903,14 @@ stream-splicer@^2.0.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -9273,6 +10939,20 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== + dependencies: + ansi-regex "^3.0.0" + strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -9306,6 +10986,11 @@ strip-dirs@^2.0.0: dependencies: is-natural-number "^4.0.1" +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== + strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" @@ -9318,6 +11003,11 @@ strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed "1.0.0" +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + strip-outer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" @@ -9378,6 +11068,11 @@ superagent@^5.2.1: readable-stream "^3.6.0" semver "^7.3.2" +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -9421,6 +11116,16 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar-fs@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad" + integrity sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA== + dependencies: + chownr "^1.1.1" + mkdirp "^0.5.1" + pump "^3.0.0" + tar-stream "^2.0.0" + tar-stream@^1.5.2: version "1.6.2" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" @@ -9434,6 +11139,17 @@ tar-stream@^1.5.2: to-buffer "^1.1.1" xtend "^4.0.0" +tar-stream@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + tar@^6.0.1, tar@^6.0.2, tar@^6.1.0, tar@^6.1.11, tar@^6.1.2: version "6.1.13" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.13.tgz#46e22529000f612180601a6fe0680e7da508847b" @@ -9446,6 +11162,21 @@ tar@^6.0.1, tar@^6.0.2, tar@^6.1.0, tar@^6.1.11, tar@^6.1.2: mkdirp "^1.0.3" yallist "^4.0.0" +temp-file@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/temp-file/-/temp-file-3.4.0.tgz#766ea28911c683996c248ef1a20eea04d51652c7" + integrity sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg== + dependencies: + async-exit-hook "^2.0.1" + fs-extra "^10.0.0" + +term-size@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + integrity sha512-7dPUZQGy/+m3/wjVz3ZW5dobSoD/02NxJpoXUX0WIyjfVS3l0c+b/+9phIDFA7FHzkYtwtMFgeGZ/Y8jVTeqQQ== + dependencies: + execa "^0.7.0" + terser-webpack-plugin@^5.1.3: version "5.3.6" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" @@ -9468,9 +11199,9 @@ terser@5.11.0: source-map-support "~0.5.20" terser@^5.14.1: - version "5.16.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.1.tgz#5af3bc3d0f24241c7fb2024199d5c461a1075880" - integrity sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw== + version "5.16.4" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.4.tgz#51284b440b93242291a98f2a9903c024cfb70e6e" + integrity sha512-5yEGuZ3DZradbogeYQ1NaGz7rXVBDWujWlx1PT8efXO6Txn+eWbfKqB2bTDVmFXmePFkoLU6XI8UektMIEA0ug== dependencies: "@jridgewell/source-map" "^0.3.2" acorn "^8.5.0" @@ -9506,7 +11237,7 @@ through2@^4.0.2: dependencies: readable-stream "3" -"through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8: +"through@>=2.2.7 <3", through@X.X.X, through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -9544,6 +11275,13 @@ tiny-secp256k1@^1.1.1, tiny-secp256k1@^1.1.3: elliptic "^6.4.0" nan "^2.13.2" +tmp@0.0.30: + version "0.0.30" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" + integrity sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w== + dependencies: + os-tmpdir "~1.0.1" + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -9551,6 +11289,13 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmp@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + to-buffer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" @@ -9561,6 +11306,11 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -9573,6 +11323,14 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -9590,28 +11348,28 @@ trim-repeated@^1.0.0: dependencies: escape-string-regexp "^1.0.2" +truncate-utf8-bytes@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" + integrity sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ== + dependencies: + utf8-byte-length "^1.0.1" + ts-custom-error@^3.0.0: version "3.3.1" resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-3.3.1.tgz#8bd3c8fc6b8dc8e1cb329267c45200f1e17a65d1" integrity sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A== -ts-node@^10.8.2: - version "10.9.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" - integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== +ts-node@9.1.1: + version "9.1.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" + integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" arg "^4.1.0" create-require "^1.1.0" diff "^4.0.1" make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" + source-map-support "^0.5.17" yn "3.1.1" tslib@2.3.1: @@ -9619,15 +11377,60 @@ tslib@2.3.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== -tslib@^1.10.0, tslib@^1.7.1, tslib@^1.9.0: +tslib@^1.10.0, tslib@^1.13.0, tslib@^1.7.1, tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" - integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== + version "2.5.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" + integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== + +tslint-config-prettier@1.18.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz#75f140bde947d35d8f0d238e0ebf809d64592c37" + integrity sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg== + +tslint-config-valorsoft@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tslint-config-valorsoft/-/tslint-config-valorsoft-2.2.1.tgz#25dab1b8a0d5e78cf674b9a616f3879ac91ca5f4" + integrity sha512-0tMQrFGII2ffPwSwvL7ODBGRlLGuXakKLGDDcaILbJumdiZyQY8E+n1Hknb2RB7a7JT+A9iNl6jRS24O+kLcZA== + +tslint-plugin-prettier@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tslint-plugin-prettier/-/tslint-plugin-prettier-2.3.0.tgz#73fe71bf9f03842ac48c104122ca9b1de012ecf4" + integrity sha512-F9e4K03yc9xuvv+A0v1EmjcnDwpz8SpCD8HzqSDe0eyg34cBinwn9JjmnnRrNAs4HdleRQj7qijp+P/JTxt4vA== + dependencies: + eslint-plugin-prettier "^2.2.0" + lines-and-columns "^1.1.6" + tslib "^1.7.1" + +tslint@6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904" + integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg== + dependencies: + "@babel/code-frame" "^7.0.0" + builtin-modules "^1.1.1" + chalk "^2.3.0" + commander "^2.12.1" + diff "^4.0.1" + glob "^7.1.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + mkdirp "^0.5.3" + resolve "^1.3.2" + semver "^5.3.0" + tslib "^1.13.0" + tsutils "^2.29.0" + +tsutils@^2.29.0: + version "2.29.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" + integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== + dependencies: + tslib "^1.8.1" tty-browserify@0.0.1: version "0.0.1" @@ -9646,6 +11449,11 @@ tweetnacl-util@^0.15.1: resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + tweetnacl@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" @@ -9663,6 +11471,11 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== +type-fest@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" + integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -9703,11 +11516,24 @@ typescript@4.4.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c" integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== +ua-parser-js@^0.7.30: + version "0.7.33" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" + integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== + umd@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" integrity sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow== +unbzip2-stream@1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" + integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + unbzip2-stream@^1.0.9: version "1.4.3" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" @@ -9778,6 +11604,13 @@ unique-slug@^3.0.0: dependencies: imurmurhash "^0.1.4" +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + integrity sha512-ODgiYu03y5g76A1I9Gt0/chLCzQjvzDy7DsZGsLOE/1MrF6wriEskSncj1+/C58Xk/kPZDppSctDybCwOSaGAg== + dependencies: + crypto-random-string "^1.0.0" + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -9798,7 +11631,7 @@ untildify@^4.0.0: resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== -update-browserslist-db@^1.0.9: +update-browserslist-db@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== @@ -9806,6 +11639,24 @@ update-browserslist-db@^1.0.9: escalade "^3.1.1" picocolors "^1.0.0" +update-notifier@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-3.0.1.tgz#78ecb68b915e2fd1be9f767f6e298ce87b736250" + integrity sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ== + dependencies: + boxen "^3.0.0" + chalk "^2.0.1" + configstore "^4.0.0" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.1.0" + is-npm "^3.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -9820,6 +11671,13 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== + dependencies: + prepend-http "^2.0.0" + url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" @@ -9833,6 +11691,11 @@ url@~0.11.0: punycode "1.3.2" querystring "0.2.0" +utf8-byte-length@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" + integrity sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA== + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -9866,10 +11729,10 @@ uuid@8.3.2, uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== validate-npm-package-license@^3.0.1: version "3.0.4" @@ -9893,24 +11756,38 @@ varuint-bitcoin@^1.0.4: dependencies: safe-buffer "^5.1.1" -vary@~1.1.2: +vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + vm-browserify@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== vm2@^3.9.8: - version "3.9.13" - resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.13.tgz#774a1a3d73b9b90b1aa45bcc5f25e349f2eef649" - integrity sha512-0rvxpB8P8Shm4wX2EKOiMp7H2zq+HUE/UwodY0pCZXs9IffIKZq6vUti5OgkVCTakKo9e/fgO4X1fkwfjWxE3Q== + version "3.9.14" + resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.14.tgz#964042b474cf1e6e4f475a39144773cdb9deb734" + integrity sha512-HgvPHYHeQy8+QhzlFryvSteA4uQLBCOub02mgqdR+0bN/akRZ48TGB1v0aCv7ksyc0HXx16AZtMHKS38alc6TA== dependencies: acorn "^8.7.0" acorn-walk "^8.2.0" +void-elements@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" + integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== + watchpack@^2.3.1: version "2.4.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" @@ -9933,6 +11810,31 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +webdriver-js-extender@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz#57d7a93c00db4cc8d556e4d3db4b5db0a80c3bb7" + integrity sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ== + dependencies: + "@types/selenium-webdriver" "^3.0.0" + selenium-webdriver "^3.0.1" + +webdriver-manager@^12.1.7: + version "12.1.9" + resolved "https://registry.yarnpkg.com/webdriver-manager/-/webdriver-manager-12.1.9.tgz#8d83543b92711b7217b39fef4cda958a4703d2df" + integrity sha512-Yl113uKm8z4m/KMUVWHq1Sjtla2uxEBtx2Ue3AmIlnlPAKloDn/Lvmy6pqWCUersVISpdMeVpAaGbNnvMuT2LQ== + dependencies: + adm-zip "^0.5.2" + chalk "^1.1.1" + del "^2.2.0" + glob "^7.0.3" + ini "^1.3.4" + minimist "^1.2.0" + q "^1.4.1" + request "^2.87.0" + rimraf "^2.5.2" + semver "^5.3.0" + xml2js "^0.4.17" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -10096,6 +11998,13 @@ which-typed-array@^1.1.2: has-tostringtag "^1.0.0" is-typed-array "^1.1.10" +which@^1.2.1, which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -10110,6 +12019,13 @@ wide-align@^1.1.5: dependencies: string-width "^1.0.2 || 2 || 3 || 4" +widest-line@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" + integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== + dependencies: + string-width "^2.1.1" + wif@^2.0.1, wif@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/wif/-/wif-2.0.6.tgz#08d3f52056c66679299726fade0d432ae74b4704" @@ -10166,6 +12082,15 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +write-file-atomic@^2.0.0: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + write-file-atomic@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" @@ -10176,12 +12101,27 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + ws@^8.1.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" - integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== + version "8.12.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.1.tgz#c51e583d79140b5e42e39be48c934131942d4a8f" + integrity sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew== + +ws@~8.11.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" + integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== -xml2js@^0.4.23: +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + integrity sha512-1Dly4xqlulvPD3fZUQJLY+FUIeqN3N2MM3uqe4rCJftAvOjFa3jFGfctOgluGx4ahPbUCsZkmJILiP0Vi4T6lQ== + +xml2js@^0.4.17, xml2js@^0.4.23: version "0.4.23" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== @@ -10219,6 +12159,11 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -10250,6 +12195,11 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" @@ -10288,10 +12238,23 @@ yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yargs@^16.1.1: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yargs@^17.2.1: - version "17.6.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.2.tgz#2e23f2944e976339a1ee00f18c77fedee8332541" - integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== + version "17.7.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" + integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== dependencies: cliui "^8.0.1" escalade "^3.1.1"