diff --git a/Flipper.podspec b/Flipper.podspec index d9da51b9577..14518f7f082 100644 --- a/Flipper.podspec +++ b/Flipper.podspec @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -flipperkit_version = '0.210.0' +flipperkit_version = '0.212.0' Pod::Spec.new do |spec| spec.name = 'Flipper' spec.cocoapods_version = '>= 1.10' diff --git a/FlipperKit.podspec b/FlipperKit.podspec index 9adbb35e6cf..02c43dce0e6 100644 --- a/FlipperKit.podspec +++ b/FlipperKit.podspec @@ -4,7 +4,7 @@ # LICENSE file in the root directory of this source tree. folly_compiler_flags = '-DDEBUG=1 -DFLIPPER_OSS=1 -DFB_SONARKIT_ENABLED=1 -DFOLLY_HAVE_BACKTRACE=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_HAVE_LIBGFLAGS=0 -DFOLLY_HAVE_LIBJEMALLOC=0 -DFOLLY_HAVE_PREADV=0 -DFOLLY_HAVE_PWRITEV=0 -DFOLLY_HAVE_TFO=0 -DFOLLY_USE_SYMBOLIZER=0' -flipperkit_version = '0.210.0' +flipperkit_version = '0.212.0' Pod::Spec.new do |spec| spec.name = 'FlipperKit' spec.version = flipperkit_version diff --git a/android/plugins/jetpack-compose/build.gradle b/android/plugins/jetpack-compose/build.gradle index 97390530896..a4e32371285 100644 --- a/android/plugins/jetpack-compose/build.gradle +++ b/android/plugins/jetpack-compose/build.gradle @@ -33,10 +33,3 @@ android { apply plugin: 'com.vanniktech.maven.publish' - -import com.vanniktech.maven.publish.SonatypeHost -mavenPublishing { - // Disable javadoc publishing - publishToMavenCentral(SonatypeHost.DEFAULT, false) -} - diff --git a/android/src/main/cpp/sonar.cpp b/android/src/main/cpp/sonar.cpp index 3bfa8d3a350..d9415668ebf 100644 --- a/android/src/main/cpp/sonar.cpp +++ b/android/src/main/cpp/sonar.cpp @@ -343,6 +343,13 @@ class JFlipperWebSocket : public facebook::flipper::FlipperSocket { if (socket_ == nullptr) { return; } + // Ensure the payload size is valid before sending. + // The maximum allowed size for a message payload is 2^53 - 1. But that is + // for the entire message, including any additional metadata. + if (message.length() > pow(2, 53) - 1) { + throw std::length_error("Payload is too big to send"); + } + socket_->send(message); completion(); } diff --git a/android/src/main/java/com/facebook/flipper/plugins/react/ReactFlipperPlugin.java b/android/src/main/java/com/facebook/flipper/plugins/react/ReactFlipperPlugin.java index ac75701f6fc..ec2fd35a554 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/react/ReactFlipperPlugin.java +++ b/android/src/main/java/com/facebook/flipper/plugins/react/ReactFlipperPlugin.java @@ -10,7 +10,7 @@ import com.facebook.flipper.core.FlipperConnection; import com.facebook.flipper.core.FlipperPlugin; -// This plugin is not needed, but kept here for backward compatilibty +// This plugin is not needed, but kept here for backward compatibility @Deprecated public class ReactFlipperPlugin implements FlipperPlugin { diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/UIDebuggerFlipperPlugin.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/UIDebuggerFlipperPlugin.kt index 76dc8331953..003c51d8b09 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/UIDebuggerFlipperPlugin.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/UIDebuggerFlipperPlugin.kt @@ -49,6 +49,8 @@ class UIDebuggerFlipperPlugin(val context: UIDContext) : FlipperPlugin { MetadataUpdateEvent(MetadataRegister.extractPendingMetadata()))) context.treeObserverManager.start() + + context.connectionListeners.forEach { it.onConnect() } } @Throws(Exception::class) @@ -59,6 +61,8 @@ class UIDebuggerFlipperPlugin(val context: UIDContext) : FlipperPlugin { context.treeObserverManager.stop() context.bitmapPool.recycleAll() + context.connectionListeners.forEach { it.onDisconnect() } + context.clearFrameworkEvents() } override fun runInBackground(): Boolean { diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/UIDContext.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/UIDContext.kt index 3142b019339..83ed3f111fd 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/UIDContext.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/core/UIDContext.kt @@ -11,19 +11,29 @@ import android.app.Application import com.facebook.flipper.core.FlipperConnection import com.facebook.flipper.plugins.uidebugger.common.BitmapPool import com.facebook.flipper.plugins.uidebugger.descriptors.DescriptorRegister +import com.facebook.flipper.plugins.uidebugger.model.FrameworkEvent import com.facebook.flipper.plugins.uidebugger.model.FrameworkEventMetadata import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverFactory import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverManager import com.facebook.flipper.plugins.uidebugger.scheduler.SharedThrottle import com.facebook.flipper.plugins.uidebugger.traversal.PartialLayoutTraversal -data class UIDContext( +interface ConnectionListener { + fun onConnect() + + fun onDisconnect() +} + +class UIDContext( val applicationRef: ApplicationRef, val connectionRef: ConnectionRef, val descriptorRegister: DescriptorRegister, val observerFactory: TreeObserverFactory, - val frameworkEventMetadata: MutableList + val frameworkEventMetadata: MutableList, + val connectionListeners: MutableList, + private val pendingFrameworkEvents: MutableList ) { + val layoutTraversal: PartialLayoutTraversal = PartialLayoutTraversal(descriptorRegister, observerFactory) @@ -31,6 +41,22 @@ data class UIDContext( val sharedThrottle: SharedThrottle = SharedThrottle() val bitmapPool = BitmapPool() + fun addFrameworkEvent(frameworkEvent: FrameworkEvent) { + synchronized(pendingFrameworkEvents) { pendingFrameworkEvents.add(frameworkEvent) } + } + + fun extractPendingFrameworkEvents(): List { + synchronized(pendingFrameworkEvents) { + val copy = pendingFrameworkEvents.toList() + pendingFrameworkEvents.clear() + return copy + } + } + + fun clearFrameworkEvents() { + synchronized(pendingFrameworkEvents) { pendingFrameworkEvents.clear() } + } + companion object { fun create(application: Application): UIDContext { return UIDContext( @@ -38,7 +64,9 @@ data class UIDContext( ConnectionRef(null), descriptorRegister = DescriptorRegister.withDefaults(), observerFactory = TreeObserverFactory.withDefaults(), - frameworkEventMetadata = mutableListOf()) + frameworkEventMetadata = mutableListOf(), + connectionListeners = mutableListOf(), + pendingFrameworkEvents = mutableListOf()) } } } diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/FrameworkEvents.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/FrameworkEvents.kt index 76ebbea0474..a5cd7f77df1 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/FrameworkEvents.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/FrameworkEvents.kt @@ -17,7 +17,11 @@ data class FrameworkEventMetadata( @kotlinx.serialization.Serializable data class FrameworkEvent( + val treeId: Id, val nodeId: Id, val type: String, - val timestamp: Long, + val timestamp: Long, // millis since epoch + val duration: Long?, // in Nanoseconds + val thread: String, + val payload: Map // can be json ) diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/observers/TreeObserverManager.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/observers/TreeObserverManager.kt index 0d372226781..141adbb36ac 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/observers/TreeObserverManager.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/observers/TreeObserverManager.kt @@ -108,7 +108,7 @@ class TreeObserverManager(val context: UIDContext) { val workerThreadStartTimestamp = System.currentTimeMillis() val nodes = batchedUpdate.updates.flatMap { it.deferredNodes.map { it.value() } } - val frameworkEvents = batchedUpdate.updates.flatMap { it.frameworkEvents ?: listOf() } + val frameworkEvents = context.extractPendingFrameworkEvents() val snapshotUpdate = batchedUpdate.updates.find { it.snapshot != null } val deferredComputationEndTimestamp = System.currentTimeMillis() diff --git a/desktop/app/package.json b/desktop/app/package.json index 16f38b06e27..63f1c6baa93 100644 --- a/desktop/app/package.json +++ b/desktop/app/package.json @@ -20,12 +20,12 @@ "flipper-server-companion": "0.0.0", "flipper-server-core": "0.0.0", "flipper-ui-core": "0.0.0", - "fs-extra": "^11.1.0", + "fs-extra": "^11.1.1", "invariant": "^2.2.2", "metro-runtime": "^0.70.2", "pretty-format": "^27.5.0", "reconnecting-websocket": "^4.4.0", - "ws": "8.8.0" + "ws": "8.13.0" }, "optionalDependencies": {}, "devDependencies": { diff --git a/desktop/app/src/electron/initializeElectron.tsx b/desktop/app/src/electron/initializeElectron.tsx index 55974125bab..c2e4311ca86 100644 --- a/desktop/app/src/electron/initializeElectron.tsx +++ b/desktop/app/src/electron/initializeElectron.tsx @@ -134,7 +134,6 @@ export async function initializeElectron( return { data, name: fileName, - path: filePath, }; }), ); diff --git a/desktop/app/src/init.tsx b/desktop/app/src/init.tsx index 1bb6f7c37ae..989cd73bcf1 100644 --- a/desktop/app/src/init.tsx +++ b/desktop/app/src/init.tsx @@ -28,6 +28,7 @@ import { loadLauncherSettings, loadProcessConfig, loadSettings, + sessionId, setupPrefetcher, startFlipperServer, startServer, @@ -45,9 +46,7 @@ import constants from './fb-stubs/constants'; import {initializeElectron} from './electron/initializeElectron'; import path from 'path'; import fs from 'fs-extra'; -import os from 'os'; import {ElectronIpcClientRenderer} from './electronIpc'; -import {checkSocketInUse, makeSocketPath} from 'flipper-server-core'; import {KeytarModule} from 'flipper-server-core/src/utils/keytar'; import {initCompanionEnv} from 'flipper-server-companion'; import ReconnectingWebSocket from 'reconnecting-websocket'; @@ -118,8 +117,6 @@ async function getFlipperServer( const serverUsageEnabled = gatekeepers['flipper_desktop_use_server']; const settings = await loadSettings(); - - const socketPath = await makeSocketPath(); const port = 52342; /** * Only attempt to use the auth token if one is available. Otherwise, @@ -134,7 +131,6 @@ async function getFlipperServer( // check first with the actual TCP socket const searchParams = new URLSearchParams(token ? {token} : {}); const TCPconnectionURL = new URL(`ws://localhost:${port}?${searchParams}`); - const UDSconnectionURL = new URL(`ws+unix://${socketPath}`); /** * Attempt to shutdown a running instance of Flipper server. @@ -159,12 +155,7 @@ async function getFlipperServer( */ if (await checkPortInUse(port)) { console.warn(`[flipper-server] TCP port ${port} is already in use.`); - await shutdown(TCPconnectionURL); - } else if (await checkSocketInUse(socketPath)) { - console.warn(`[flipper-server] UDS socket is already in use.`); - - await shutdown(UDSconnectionURL); } const [homePath, tempPath, desktopPath] = await Promise.all([ @@ -176,6 +167,7 @@ async function getFlipperServer( const getEmbeddedServer = async () => { const server = new FlipperServerImpl( { + sessionId, environmentInfo, env: parseEnvironmentVariables(env), gatekeepers: gatekeepers, @@ -206,7 +198,6 @@ async function getFlipperServer( const {readyForIncomingConnections} = await startServer({ staticPath, entry: 'index.web.dev.html', - tcp: false, port, }); @@ -224,9 +215,7 @@ async function getFlipperServer( await server.connect(); await readyForIncomingConnections(server, companionEnv); - return getExternalServer( - os.platform() === 'win32' ? TCPconnectionURL : UDSconnectionURL, - ); + return getExternalServer(TCPconnectionURL); } return getEmbeddedServer(); } diff --git a/desktop/doctor/package.json b/desktop/doctor/package.json index ca06988a149..3d728f0882b 100644 --- a/desktop/doctor/package.json +++ b/desktop/doctor/package.json @@ -26,8 +26,8 @@ "author": "Facebook, Inc", "dependencies": { "envinfo": "^7.8.1", - "fb-watchman": "^2.0.1", + "fb-watchman": "^2.0.2", "flipper-common": "0.0.0", - "fs-extra": "^11.1.0" + "fs-extra": "^11.1.1" } } diff --git a/desktop/eslint-plugin-flipper/package.json b/desktop/eslint-plugin-flipper/package.json index 032cd1429ca..80291a94691 100644 --- a/desktop/eslint-plugin-flipper/package.json +++ b/desktop/eslint-plugin-flipper/package.json @@ -12,7 +12,7 @@ "dependencies": { "@typescript-eslint/experimental-utils": "^5.22.0", "@typescript-eslint/parser": "^5.55.0", - "fs-extra": "^11.1.0" + "fs-extra": "^11.1.1" }, "devDependencies": {}, "scripts": { diff --git a/desktop/examples/headless-demo/package.json b/desktop/examples/headless-demo/package.json index 2de0d9f8b03..7daf9d73397 100644 --- a/desktop/examples/headless-demo/package.json +++ b/desktop/examples/headless-demo/package.json @@ -16,7 +16,7 @@ "start": "node index.js" }, "dependencies": { - "ws": "^8.6.0" + "ws": "^8.13.0" }, "files": [ "*.js", diff --git a/desktop/examples/headless-tic-tac-toe/package.json b/desktop/examples/headless-tic-tac-toe/package.json index cd807239082..db4e7fe6c4e 100644 --- a/desktop/examples/headless-tic-tac-toe/package.json +++ b/desktop/examples/headless-tic-tac-toe/package.json @@ -17,7 +17,7 @@ }, "dependencies": { "inquirer": "^8.2.4", - "ws": "^8.6.0" + "ws": "^8.13.0" }, "files": [ "*.js", diff --git a/desktop/flipper-common/src/index.tsx b/desktop/flipper-common/src/index.tsx index 3d33a2d98d8..7925006b65e 100644 --- a/desktop/flipper-common/src/index.tsx +++ b/desktop/flipper-common/src/index.tsx @@ -20,6 +20,8 @@ export { setLoggerInstance, NoopLogger, } from './utils/Logger'; +export * from './utils/LoggerTailer'; +export * from './utils/ScribeLogger'; export * from './server-types'; export * from './companion-types'; export * from './ServerAddOn'; diff --git a/desktop/flipper-common/src/server-types.tsx b/desktop/flipper-common/src/server-types.tsx index a3b94e467af..12e3843de0a 100644 --- a/desktop/flipper-common/src/server-types.tsx +++ b/desktop/flipper-common/src/server-types.tsx @@ -319,8 +319,8 @@ export type FlipperServerCommands = { name: string, ) => Promise; 'plugins-install-from-npm': (name: string) => Promise; - 'plugins-install-from-file': ( - path: string, + 'plugins-install-from-content': ( + contents: string, ) => Promise; 'plugins-remove-plugins': (names: string[]) => Promise; 'plugins-server-add-on-start': ( @@ -351,6 +351,7 @@ export type FlipperServerCommands = { options: { timeout?: number; internGraphUrl?: string; + headers?: Record; }, ) => Promise; 'intern-graph-get': ( @@ -359,6 +360,7 @@ export type FlipperServerCommands = { options: { timeout?: number; internGraphUrl?: string; + headers?: Record; }, ) => Promise; 'intern-upload-scribe-logs': ( @@ -524,6 +526,7 @@ export type FlipperServerConfig = { validWebSocketOrigins: string[]; environmentInfo: EnvironmentInfo; type?: FlipperServerType; + sessionId: string; }; export interface FlipperServerExecOptions { diff --git a/desktop/flipper-ui-core/src/consoleLogTailer.tsx b/desktop/flipper-common/src/utils/LoggerTailer.tsx similarity index 73% rename from desktop/flipper-ui-core/src/consoleLogTailer.tsx rename to desktop/flipper-common/src/utils/LoggerTailer.tsx index cbaa32f7173..98d50816bd0 100644 --- a/desktop/flipper-ui-core/src/consoleLogTailer.tsx +++ b/desktop/flipper-common/src/utils/LoggerTailer.tsx @@ -7,25 +7,33 @@ * @format */ -import {getStringFromErrorLike, LoggerTypes} from 'flipper-common'; - -const logLevels: LoggerTypes[] = ['debug', 'info', 'warn', 'error']; +import {getStringFromErrorLike} from './errors'; +import {LoggerTypes} from './Logger'; +export const logLevels: LoggerTypes[] = ['debug', 'info', 'warn', 'error']; export type LogTailer = (level: LoggerTypes, ...data: Array) => void; const logTailers: LogTailer[] = []; +let initialized = false; export function addLogTailer(handler: LogTailer) { logTailers.push(handler); } export function initLogTailer() { + if (initialized) { + return; + } + + initialized = true; + const originalConsole: {[key: string]: any} = console; - //store the raw console log functions here + // Store the raw console log functions here const originalConsoleLogFunctions: {[key: string]: (...args: any) => void} = {} as { [key: string]: (...args: any) => void; }; + // React Devtools also patches the console methods: // https://github.com/facebook/react/blob/206d61f72214e8ae5b935f0bf8628491cb7f0797/packages/react-devtools-shared/src/backend/console.js#L141 // Not using a proxy object here because it isn't compatible with their patching process. @@ -52,16 +60,16 @@ export function initLogTailer() { } function transformLogLevel(level: LoggerTypes, message: string) { - if ( - level === 'error' && - message.includes('ResizeObserver loop limit exceeded') - ) { - return 'warn'; - } - - // Axios will create rather unhelpful error messages which lead to unactionable tasks, e.g. T150636191 - if (level === 'error' && message.endsWith('Network Error')) { - return 'warn'; + if (level === 'error') { + // Error comes from one of our dependencies and is not actionable + if (message.includes('ResizeObserver loop limit exceeded')) { + return 'warn'; + } + // Axios will create rather unhelpful error messages which + // lead to unactionable tasks, e.g. T150636191 + if (message.endsWith('Network Error')) { + return 'warn'; + } } return level; diff --git a/desktop/flipper-common/src/utils/ScribeLogger.tsx b/desktop/flipper-common/src/utils/ScribeLogger.tsx new file mode 100644 index 00000000000..57252b84710 --- /dev/null +++ b/desktop/flipper-common/src/utils/ScribeLogger.tsx @@ -0,0 +1,94 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +const FLUSH_TIMEOUT = 500; +const MAX_MESSAGES = 1000; + +export type ScribeMessage = { + category: string; + message: string; +}; + +/** + * Send messages to arbitrary Scribe categories. This is useful to log data to + * LogView, Scuba, Hive, etc. + */ +export class ScribeLogger { + constructor( + sender: (messages: Array) => Promise, + disabled = false, + flushTimeout = FLUSH_TIMEOUT, + ) { + this.isFlushPending = false; + this.queue = []; + this.sendMessages = sender; + this.flushTimeout = flushTimeout; + this.disabled = disabled; + } + + isFlushPending: boolean; + queue: Array; + sendMessages: (messages: Array) => Promise; + flushTimeout: number; + disabled: boolean; + + /** + * Send all the queued messages and reset. + */ + flushQueue = async () => { + const messages = this.queue.splice(0); // copy & clear + try { + // send all the message currently in the queue + await this.sendMessages(messages); + } catch (e) { + console.debug(`[ScribeLogger] Failed to send messages: ${e}`); + // restore messages if emit failed + this.queue = messages.concat(this.queue); + this.enforceQueueLimit(); + } finally { + // reset the queue + this.isFlushPending = false; + } + }; + + /** + * Add a message to be queued. Start a queue flush timer if one isn't already pending. + */ + queueSend(message: ScribeMessage) { + this.queue.push(message); + this.enforceQueueLimit(); + + // start a flush timer if none exists + if (this.isFlushPending === false) { + this.isFlushPending = true; + if (this.flushTimeout >= 0) { + setTimeout(this.flushQueue, FLUSH_TIMEOUT); + } else { + this.flushQueue(); + } + } + } + + enforceQueueLimit() { + if (this.queue.length > MAX_MESSAGES) { + console.debug('[ScribeLogger] Queue full, dropping oldest messages'); + this.queue = this.queue.slice(Math.floor(MAX_MESSAGES / 10)); + } + } + + /** + * Messages are not guaranteed to be sent right away. + */ + send(message: ScribeMessage) { + if (this.disabled) { + return; + } + this.queueSend(message); + } +} diff --git a/desktop/flipper-common/src/utils/isProduction.tsx b/desktop/flipper-common/src/utils/isProduction.tsx index 0fe3e17e8b1..d2b1c556f70 100644 --- a/desktop/flipper-common/src/utils/isProduction.tsx +++ b/desktop/flipper-common/src/utils/isProduction.tsx @@ -13,6 +13,7 @@ declare const process: any; // this one, and one provided by the RenderHostConfig. Ideally they should be unified export function isProduction(): boolean { return ( - typeof process === 'undefined' || process.env.NODE_ENV === 'production' + typeof process === 'undefined' || + (process.env.NODE_ENV !== 'development' && process.env.NODE_ENV !== 'test') ); } diff --git a/desktop/flipper-dump/package.json b/desktop/flipper-dump/package.json index 3d7930c4238..ce1cbab78f6 100644 --- a/desktop/flipper-dump/package.json +++ b/desktop/flipper-dump/package.json @@ -12,7 +12,7 @@ "dependencies": { "flipper-common": "0.0.0", "flipper-server-core": "0.0.0", - "yargs": "^17.6.2" + "yargs": "^17.7.2" }, "devDependencies": { "@types/node": "^17.0.31" diff --git a/desktop/flipper-dump/src/index.tsx b/desktop/flipper-dump/src/index.tsx index 47fc8285227..bf826c0a877 100644 --- a/desktop/flipper-dump/src/index.tsx +++ b/desktop/flipper-dump/src/index.tsx @@ -16,6 +16,7 @@ import { loadLauncherSettings, loadProcessConfig, loadSettings, + sessionId, } from 'flipper-server-core'; import { ClientDescription, @@ -94,6 +95,7 @@ async function start(deviceQuery: string, appName: string, pluginId: string) { ]); const server = new FlipperServerImpl( { + sessionId, environmentInfo, env: parseEnvironmentVariables(process.env), gatekeepers: {}, diff --git a/desktop/flipper-frontend-core/package.json b/desktop/flipper-frontend-core/package.json index 2a8437733e0..6d694fc9073 100644 --- a/desktop/flipper-frontend-core/package.json +++ b/desktop/flipper-frontend-core/package.json @@ -16,7 +16,7 @@ "js-base64": "^3.7.5", "p-map": "^4.0.0", "reconnecting-websocket": "^4.4.0", - "semver": "^7.3.7" + "semver": "^7.5.4" }, "devDependencies": { "flipper-test-utils": "0.0.0" diff --git a/desktop/flipper-frontend-core/src/AbstractClient.tsx b/desktop/flipper-frontend-core/src/AbstractClient.tsx index 57b4a7a91dd..4cae97e89cd 100644 --- a/desktop/flipper-frontend-core/src/AbstractClient.tsx +++ b/desktop/flipper-frontend-core/src/AbstractClient.tsx @@ -134,10 +134,13 @@ export default abstract class AbstractClient extends EventEmitter { 'Fetch plugin timeout. Unresponsive client?', ); } catch (e) { - console.warn('[conn] Fetch plugin error', e); + console.warn('Failed to fetch plugin', e); } this.plugins = new Set(response?.plugins ?? []); - console.info('AbstractClient.loadPlugins', this.query, [...this.plugins]); + console.info( + `Received plugins from '${this.query.app}' on device '${this.query.device}'`, + [...this.plugins], + ); return this.plugins; } @@ -226,8 +229,17 @@ export default abstract class AbstractClient extends EventEmitter { this.startPluginIfNeeded(await this.getPlugin(pluginId)), ), ); - const newBackgroundPlugins = await this.getBackgroundPlugins(); - this.backgroundPlugins = new Set(newBackgroundPlugins); + let newBackgroundPlugins: PluginsArr = []; + try { + newBackgroundPlugins = await this.getBackgroundPlugins(); + this.backgroundPlugins = new Set(newBackgroundPlugins); + } catch (e: unknown) { + if ((e as Error).message.includes('timeout')) { + console.warn(e); + } else { + throw e; + } + } // diff the background plugin list, disconnect old, connect new ones oldBackgroundPlugins.forEach((plugin) => { if (!this.backgroundPlugins.has(plugin)) { diff --git a/desktop/flipper-frontend-core/src/RenderHost.tsx b/desktop/flipper-frontend-core/src/RenderHost.tsx index 27a4a057701..1662b40dd1e 100644 --- a/desktop/flipper-frontend-core/src/RenderHost.tsx +++ b/desktop/flipper-frontend-core/src/RenderHost.tsx @@ -67,7 +67,7 @@ interface NotificationConstructorOptions { // Events that are emitted from the main.ts ovr the IPC process bridge in Electron type MainProcessEvents = { 'flipper-protocol-handler': [query: string]; - 'open-flipper-file': [url: string]; + 'open-flipper-file': [name: string, data: string]; notificationEvent: [ eventName: NotificationEvents, pluginNotification: PluginNotification, @@ -88,7 +88,7 @@ type ChildProcessEvents = { }, ]; getLaunchTime: []; - componentDidMount: []; + storeRehydrated: []; }; /** diff --git a/desktop/flipper-plugin-core/src/plugin/FlipperLib.tsx b/desktop/flipper-plugin-core/src/plugin/FlipperLib.tsx index 98dd2975741..db28db2e84a 100644 --- a/desktop/flipper-plugin-core/src/plugin/FlipperLib.tsx +++ b/desktop/flipper-plugin-core/src/plugin/FlipperLib.tsx @@ -32,12 +32,12 @@ import { import {CreatePasteArgs, CreatePasteResult} from './Paste'; import {Atom} from '../state/atom'; -export type FileEncoding = 'utf-8' | 'base64'; +export type FileEncoding = 'utf-8' | 'base64' | 'binary'; export interface FileDescriptor { - data: string; + data: string | Uint8Array | undefined; name: string; - path?: string; + encoding: FileEncoding; } export interface DownloadFileResponse extends DownloadFileStartResponse { diff --git a/desktop/flipper-plugin/src/ui/FileSelector.tsx b/desktop/flipper-plugin/src/ui/FileSelector.tsx index 3b70cf6ef9c..2842f864cf2 100644 --- a/desktop/flipper-plugin/src/ui/FileSelector.tsx +++ b/desktop/flipper-plugin/src/ui/FileSelector.tsx @@ -56,7 +56,7 @@ export type FileSelectorProps = { ); const formatFileDescriptor = (fileDescriptor?: FileDescriptor) => - fileDescriptor?.path || fileDescriptor?.name; + fileDescriptor?.name; export function FileSelector({ onChange, @@ -74,14 +74,8 @@ export function FileSelector({ const onSetFiles = async () => { setLoading(true); - let defaultPath: string | undefined = files[0]?.path ?? files[0]?.name; - if (multi) { - defaultPath = files[0]?.path; - } - try { const newFileSelection = await getFlipperLib().importFile?.({ - defaultPath, extensions, title: label, encoding, @@ -126,7 +120,7 @@ export function FileSelector({ droppedFiles.map(async (droppedFile) => { const raw = await droppedFile.arrayBuffer(); - let data: string; + let data: string | Uint8Array | undefined; switch (encoding) { case 'utf-8': { data = new TextDecoder().decode(raw); @@ -136,18 +130,19 @@ export function FileSelector({ data = fromUint8Array(new Uint8Array(raw)); break; } + case 'binary': + data = new Uint8Array(raw); + break; default: { assertNever(encoding); } } - const droppedFileDescriptor: FileDescriptor = { - data: data!, + return { + data, name: droppedFile.name, - // Electron "File" has "path" attribute - path: (droppedFile as any).path, + encoding, }; - return droppedFileDescriptor; }), ); diff --git a/desktop/flipper-plugin/src/ui/MarkerTimeline.tsx b/desktop/flipper-plugin/src/ui/MarkerTimeline.tsx index 72d26a7d055..50a6cbf3fe1 100644 --- a/desktop/flipper-plugin/src/ui/MarkerTimeline.tsx +++ b/desktop/flipper-plugin/src/ui/MarkerTimeline.tsx @@ -63,14 +63,15 @@ const Point = styled(Layout.Horizontal)<{ right: 10, cursor: props.onClick ? 'pointer' : 'default', borderRadius: 3, - alignItems: 'flex-start', + alignItems: 'baseline', lineHeight: '16px', ':hover': { - backgroundColor: theme.selectionBackgroundColor, + backgroundColor: theme.backgroundWash, '> span': { whiteSpace: 'initial', }, }, + '::before': { position: 'relative', textAlign: 'center', @@ -115,12 +116,15 @@ const Time = styled.span({ }); Time.displayName = 'MakerTimeline:Time'; -const Code = styled(Typography.Text)({ +const Name = styled(Typography.Text)({ overflow: 'hidden', + opacity: 0.8, textOverflow: 'ellipsis', marginTop: -1, + marginLeft: theme.space.tiny, + fontFamily: 'monospace', }); -Code.displayName = 'MakerTimeline:Code'; +Name.displayName = 'MakerTimeline:Name'; type TimePoint = { timestamp: number; @@ -229,8 +233,8 @@ export class MarkerTimeline extends Component { number={ p.markerNames.length > 1 ? p.markerNames.length : undefined }> - {' '} - {p.markerNames.join(', ')} + {' '} + {p.markerNames.join(', ')} ); })} diff --git a/desktop/flipper-plugin/src/ui/data-inspector/DataDescription.tsx b/desktop/flipper-plugin/src/ui/data-inspector/DataDescription.tsx index f72d3cb12a7..d284aa3c94d 100644 --- a/desktop/flipper-plugin/src/ui/data-inspector/DataDescription.tsx +++ b/desktop/flipper-plugin/src/ui/data-inspector/DataDescription.tsx @@ -573,7 +573,8 @@ class DataDescriptionContainer extends PureComponent<{ case 'number': return {+val}; - + case 'bigint': + return {val.toString()}; case 'color': { const colorInfo = parseColor(val); if (typeof val === 'number' && val === 0) { diff --git a/desktop/flipper-plugin/src/ui/data-inspector/TimelineDataDescription.tsx b/desktop/flipper-plugin/src/ui/data-inspector/TimelineDataDescription.tsx index 70e937a9250..da185ea6bbd 100644 --- a/desktop/flipper-plugin/src/ui/data-inspector/TimelineDataDescription.tsx +++ b/desktop/flipper-plugin/src/ui/data-inspector/TimelineDataDescription.tsx @@ -45,6 +45,9 @@ export class TimelineDataDescription extends Component { render(): ReactNode { const moments = Object.values(this.props.timeline.time); + if (moments == null || moments.length === 0) { + return null; + } const firstMoment = moments[0].moment; const points = moments.map((value) => ({ label: value.display, @@ -69,7 +72,7 @@ export class TimelineDataDescription extends Component { )} -
+
{ diff --git a/desktop/flipper-plugin/src/ui/data-table/DataTableManager.tsx b/desktop/flipper-plugin/src/ui/data-table/DataTableManager.tsx index 853552bce68..7c659c7c5d2 100644 --- a/desktop/flipper-plugin/src/ui/data-table/DataTableManager.tsx +++ b/desktop/flipper-plugin/src/ui/data-table/DataTableManager.tsx @@ -13,7 +13,7 @@ import {MutableRefObject, Reducer, RefObject} from 'react'; import {DataSourceVirtualizer} from '../../data-source/index'; import produce, {castDraft, immerable, original} from 'immer'; import {theme} from '../theme'; -import {DataSource, _DataSourceView} from 'flipper-plugin-core'; +import {DataSource, getFlipperLib, _DataSourceView} from 'flipper-plugin-core'; export type OnColumnResize = (id: string, size: number | Percentage) => void; export type Sorting = { @@ -353,6 +353,7 @@ export const dataTableManagerReducer = produce< getValueAtPath(item, String(action.column)), { disableOthers: index === 0, // remove existing filters before adding the first + exact: true, }, ); }); @@ -485,6 +486,7 @@ export function createDataTableManager( dispatch({type: 'sortColumn', column, direction}); }, setSearchValue(value, addToHistory = false) { + getFlipperLib().logger.track('usage', 'data-table:filter:search'); dispatch({type: 'setSearchValue', value, addToHistory}); }, toggleSearchValue() { @@ -506,9 +508,11 @@ export function createDataTableManager( dispatch({type: 'setShowNumberedHistory', showNumberedHistory}); }, addColumnFilter(column, value, options = {}) { + getFlipperLib().logger.track('usage', 'data-table:filter:add-column'); dispatch({type: 'addColumnFilter', column, value, options}); }, removeColumnFilter(column, label) { + getFlipperLib().logger.track('usage', 'data-table:filter:remove-column'); dispatch({type: 'removeColumnFilter', column, label}); }, setFilterExceptions(exceptions: string[] | undefined) { diff --git a/desktop/flipper-plugin/src/ui/data-table/__tests__/DataTable.node.tsx b/desktop/flipper-plugin/src/ui/data-table/__tests__/DataTable.node.tsx index aff5bf3740e..9b7012cba98 100644 --- a/desktop/flipper-plugin/src/ui/data-table/__tests__/DataTable.node.tsx +++ b/desktop/flipper-plugin/src/ui/data-table/__tests__/DataTable.node.tsx @@ -14,12 +14,15 @@ import {createDataSource} from 'flipper-plugin-core'; import {computeDataTableFilter, DataTableManager} from '../DataTableManager'; import {Button} from 'antd'; import {sleep} from 'flipper-common'; +import {TestUtils, _setFlipperLibImplementation} from 'flipper-plugin-core'; type Todo = { title: string; done: boolean; }; +_setFlipperLibImplementation(TestUtils.createMockFlipperLib()); + function createTestDataSource() { return createDataSource([ { diff --git a/desktop/flipper-server-client/src/FlipperServerClient.tsx b/desktop/flipper-server-client/src/FlipperServerClient.tsx index 834e91fce48..0993bd0e7a4 100644 --- a/desktop/flipper-server-client/src/FlipperServerClient.tsx +++ b/desktop/flipper-server-client/src/FlipperServerClient.tsx @@ -50,7 +50,7 @@ export function createFlipperServerWithSocket( new Error( `Failed to connect to the server in a timely manner. It may be unresponsive. Run the following from the terminal - 'sudo lsof -i :52342' and kill the listed process, if any.`, + 'sudo kill $(lsof -t -i :52342)' as to kill any existing running instance, if any.`, ), ); }, CONNECTION_TIMEOUT); diff --git a/desktop/flipper-server-core/package.json b/desktop/flipper-server-core/package.json index a37668370f3..f52f61806fb 100644 --- a/desktop/flipper-server-core/package.json +++ b/desktop/flipper-server-core/package.json @@ -25,7 +25,6 @@ "flipper-server-companion": "0.0.0", "form-data": "^4.0.0", "fs-extra": "^11.1.0", - "http-proxy": "^1.18.1", "invariant": "^2.2.4", "js-base64": "^3.7.5", "jsonwebtoken": "^9.0.0", @@ -52,7 +51,6 @@ "devDependencies": { "@types/archiver": "^5.3.1", "@types/express": "^4.17.13", - "@types/http-proxy": "^1.17.8", "@types/invariant": "^2.2.35", "@types/jsonwebtoken": "^9.0.1", "@types/memorystream": "^0.3.0", @@ -65,7 +63,9 @@ "@types/split2": "^3.2.1", "@types/tmp": "^0.2.3", "@types/which": "^2.0.1", - "@types/ws": "^8.5.3" + "@types/ws": "^8.5.3", + "@types/mock-fs": "^4.13.1", + "mock-fs": "^5.2.0" }, "peerDependencies": {}, "scripts": { diff --git a/desktop/flipper-server-core/src/FlipperServerImpl.tsx b/desktop/flipper-server-core/src/FlipperServerImpl.tsx index 511cd200370..23f41af1401 100644 --- a/desktop/flipper-server-core/src/FlipperServerImpl.tsx +++ b/desktop/flipper-server-core/src/FlipperServerImpl.tsx @@ -521,8 +521,11 @@ export class FlipperServerImpl implements FlipperServer { this.pluginManager.downloadPlugin(details), 'plugins-get-updatable-plugins': (query) => this.pluginManager.getUpdatablePlugins(query), - 'plugins-install-from-file': (path) => - this.pluginManager.installPluginFromFile(path), + 'plugins-install-from-content': (contents) => { + const bytes = Base64.toUint8Array(contents); + const buffer = Buffer.from(bytes); + return this.pluginManager.installPluginFromFileOrBuffer(buffer); + }, 'plugins-install-from-marketplace': (name: string) => this.pluginManager.installPluginForMarketplace(name), 'plugins-install-from-npm': (name) => diff --git a/desktop/flipper-server-core/src/app-connectivity/ServerWebSocket.tsx b/desktop/flipper-server-core/src/app-connectivity/ServerWebSocket.tsx index 8bfe99c42db..b380ff97abe 100644 --- a/desktop/flipper-server-core/src/app-connectivity/ServerWebSocket.tsx +++ b/desktop/flipper-server-core/src/app-connectivity/ServerWebSocket.tsx @@ -36,9 +36,8 @@ export interface ConnectionCtx { request: IncomingMessage; } -// Based on https://github.com/websockets/ws/blob/master/lib/websocket-server.js#L40, -// exposed to share with socket.io defaults. -export const WEBSOCKET_MAX_MESSAGE_SIZE = 100 * 1024 * 1024; +// This is the maximum size of a message that can be received in a single websocket message. +export const WEBSOCKET_MAX_MESSAGE_SIZE = Math.pow(2, 53) - 1; /** * It serves as a base class for WebSocket based servers. It delegates the 'connection' diff --git a/desktop/flipper-server-core/src/devices/ios/iOSContainerUtility.tsx b/desktop/flipper-server-core/src/devices/ios/iOSContainerUtility.tsx index beeddcde8da..935f36d60ee 100644 --- a/desktop/flipper-server-core/src/devices/ios/iOSContainerUtility.tsx +++ b/desktop/flipper-server-core/src/devices/ios/iOSContainerUtility.tsx @@ -28,6 +28,7 @@ export type IdbConfig = { // Use debug to get helpful logs when idb fails const IDB_LOG_LEVEL = 'DEBUG'; const LOG_TAG = 'iOSContainerUtility'; +const CMD_RECORD_THROTTLE_COUNT = 10; const mutex = new Mutex(); @@ -49,6 +50,10 @@ export type DeviceTarget = { name: string; }; +let idbDeviceListing = 0; +let idbCompanionDeviceListing = 0; +let xcodeDeviceListing = 0; + async function isAvailable(idbPath: string): Promise { if (!idbPath) { return false; @@ -88,12 +93,17 @@ async function queryTargetsWithXcode( }); throw new Error('No output from command'); } - recorder.event('cmd', { - cmd, - description, - success: true, - context, - }); + + xcodeDeviceListing++; + if (xcodeDeviceListing % CMD_RECORD_THROTTLE_COUNT === 0) { + recorder.event('cmd', { + cmd, + description, + success: true, + context, + }); + } + return stdout .toString() .split('\n') @@ -141,12 +151,15 @@ async function queryTargetsWithIdb( throw new Error('No output from command'); } - recorder.event('cmd', { - cmd, - description, - success: true, - context, - }); + idbDeviceListing++; + if (idbDeviceListing % CMD_RECORD_THROTTLE_COUNT === 0) { + recorder.event('cmd', { + cmd, + description, + success: true, + context, + }); + } return parseIdbTargets(stdout.toString()); } catch (e) { @@ -187,12 +200,15 @@ async function queryTargetsWithIdbCompanion( throw new Error('No output from command'); } - recorder.event('cmd', { - cmd, - description, - success: true, - context, - }); + idbCompanionDeviceListing++; + if (idbCompanionDeviceListing % CMD_RECORD_THROTTLE_COUNT === 0) { + recorder.event('cmd', { + cmd, + description, + success: true, + context, + }); + } const devices = parseIdbTargets(stdout.toString()); if (devices.length > 0 && !isPhysicalDeviceEnabled) { diff --git a/desktop/flipper-server-core/src/fb-stubs/Logger.tsx b/desktop/flipper-server-core/src/fb-stubs/Logger.tsx new file mode 100644 index 00000000000..09a50b396b1 --- /dev/null +++ b/desktop/flipper-server-core/src/fb-stubs/Logger.tsx @@ -0,0 +1,17 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import {EnvironmentInfo, Logger, LoggerArgs, NoopLogger} from 'flipper-common'; + +export function initializeLogger( + _environmentInfo: EnvironmentInfo, + _args?: LoggerArgs, +): Logger { + return new NoopLogger(); +} diff --git a/desktop/flipper-server-core/src/fb-stubs/internRequests.tsx b/desktop/flipper-server-core/src/fb-stubs/internRequests.tsx index 5501b350fd3..eaf81aff697 100644 --- a/desktop/flipper-server-core/src/fb-stubs/internRequests.tsx +++ b/desktop/flipper-server-core/src/fb-stubs/internRequests.tsx @@ -20,6 +20,7 @@ export async function internGraphPOSTAPIRequest( options: { timeout?: number; internGraphUrl?: string; + headers?: Record; }, token: string, ): Promise { @@ -34,6 +35,7 @@ export async function internGraphGETAPIRequest( _options: { timeout?: number; internGraphUrl?: string; + headers?: Record; }, token: string, ): Promise { diff --git a/desktop/flipper-server-core/src/fb-stubs/sendScribeLogs.tsx b/desktop/flipper-server-core/src/fb-stubs/sendScribeLogs.tsx index d735a36bd51..588d0a256ae 100644 --- a/desktop/flipper-server-core/src/fb-stubs/sendScribeLogs.tsx +++ b/desktop/flipper-server-core/src/fb-stubs/sendScribeLogs.tsx @@ -7,6 +7,8 @@ * @format */ +import {ScribeMessage} from 'flipper-common'; + export async function sendScribeLogs( - _messages: {category: string; message: string}[], + _messages: ScribeMessage[], ): Promise {} diff --git a/desktop/flipper-server-core/src/index.tsx b/desktop/flipper-server-core/src/index.tsx index a43cd9ca0a1..63d995ab3b4 100644 --- a/desktop/flipper-server-core/src/index.tsx +++ b/desktop/flipper-server-core/src/index.tsx @@ -20,6 +20,7 @@ export * from './server/startFlipperServer'; export * from './server/startServer'; export * from './server/utilities'; export {isFBBuild} from './fb-stubs/constants'; +export {initializeLogger} from './fb-stubs/Logger'; export {WEBSOCKET_MAX_MESSAGE_SIZE} from './app-connectivity/ServerWebSocket'; @@ -27,3 +28,5 @@ export { getAuthToken, hasAuthToken, } from './app-connectivity/certificate-exchange/certificate-utils'; + +export {sessionId} from './sessionId'; diff --git a/desktop/flipper-server-core/src/plugins/PluginManager.tsx b/desktop/flipper-server-core/src/plugins/PluginManager.tsx index 8ba356436ca..7baa08deec6 100644 --- a/desktop/flipper-server-core/src/plugins/PluginManager.tsx +++ b/desktop/flipper-server-core/src/plugins/PluginManager.tsx @@ -28,7 +28,7 @@ import { getInstalledPlugins, getPluginVersionInstallationDir, getPluginDirNameFromPackageName, - installPluginFromFile, + installPluginFromFileOrBuffer, removePlugins, getUpdatablePlugins, getInstalledPlugin, @@ -71,7 +71,7 @@ export class PluginManager { removePlugins = removePlugins; getUpdatablePlugins = getUpdatablePlugins; getInstalledPlugin = getInstalledPlugin; - installPluginFromFile = installPluginFromFile; + installPluginFromFileOrBuffer = installPluginFromFileOrBuffer; installPluginFromNpm = installPluginFromNpm; async loadSource(path: string): Promise { @@ -186,7 +186,7 @@ export class PluginManager { await new Promise((resolve, reject) => writeStream.once('finish', resolve).once('error', reject), ); - return await installPluginFromFile(tmpFile); + return await installPluginFromFileOrBuffer(tmpFile); } } catch (error) { console.warn( diff --git a/desktop/flipper-server-core/src/server/attachSocketServer.tsx b/desktop/flipper-server-core/src/server/attachSocketServer.tsx index 4fffdf41c3c..b33bbcc5185 100644 --- a/desktop/flipper-server-core/src/server/attachSocketServer.tsx +++ b/desktop/flipper-server-core/src/server/attachSocketServer.tsx @@ -228,31 +228,32 @@ export function attachSocketServer( }); async function onClientClose(error: Error | undefined = undefined) { + console.log(`Client disconnected ${clientAddress}`); if (error) { - console.error(`Client disconnected ${clientAddress} with error`, error); - } else { - console.log(`Client disconnected ${clientAddress}`); + console.error('Client disconnected with error', error); } numberOfConnectedClients--; + + connected = false; + server.offAny(onServerEvent); + flipperServerCompanion?.destroyAll(); + if (getFlipperServerConfig().environmentInfo.isHeadlessBuild) { if (disconnectTimeout) { clearTimeout(disconnectTimeout); } + /** - * If, after 15 min, there are no more connected clients, we exit the process. + * If, after 60 seconds, there are no more connected clients, we exit the process. */ disconnectTimeout = setTimeout(() => { if (numberOfConnectedClients === 0 && isProduction()) { console.info('Shutdown as no clients are currently connected'); process.exit(0); } - }, 30 * 1000); + }, 60 * 1000); } - - connected = false; - server.offAny(onServerEvent); - flipperServerCompanion?.destroyAll(); } client.on('close', () => { diff --git a/desktop/flipper-server-core/src/server/startFlipperServer.tsx b/desktop/flipper-server-core/src/server/startFlipperServer.tsx index fc12b6e78e4..25604ffe470 100644 --- a/desktop/flipper-server-core/src/server/startFlipperServer.tsx +++ b/desktop/flipper-server-core/src/server/startFlipperServer.tsx @@ -22,6 +22,7 @@ import {getGatekeepers} from '../gk'; import {loadLauncherSettings} from '../utils/launcherSettings'; import {loadProcessConfig} from '../utils/processConfig'; import {loadSettings} from '../utils/settings'; +import {sessionId} from '../sessionId'; /** * Creates an instance of FlipperServer (FlipperServerImpl). This is the @@ -58,6 +59,7 @@ export async function startFlipperServer( ]); return new FlipperServerImpl( { + sessionId, environmentInfo, env: parseEnvironmentVariables(process.env), gatekeepers: getGatekeepers(environmentInfo.os.unixname), diff --git a/desktop/flipper-server-core/src/server/startServer.tsx b/desktop/flipper-server-core/src/server/startServer.tsx index 95554ded0c8..00db40d1e86 100644 --- a/desktop/flipper-server-core/src/server/startServer.tsx +++ b/desktop/flipper-server-core/src/server/startServer.tsx @@ -7,18 +7,13 @@ * @format */ -import os from 'os'; - import express, {Express} from 'express'; -import http, {ServerResponse} from 'http'; +import http from 'http'; import path from 'path'; import fs from 'fs-extra'; import {ServerOptions, VerifyClientCallbackSync, WebSocketServer} from 'ws'; import {WEBSOCKET_MAX_MESSAGE_SIZE} from '../app-connectivity/ServerWebSocket'; import {parse} from 'url'; -import {makeSocketPath, checkSocketInUse} from './utilities'; - -import proxy from 'http-proxy'; import exitHook from 'exit-hook'; import {attachSocketServer} from './attachSocketServer'; import {FlipperServerImpl} from '../FlipperServerImpl'; @@ -30,7 +25,6 @@ type Config = { port: number; staticPath: string; entry: string; - tcp: boolean; }; type ReadyForConnections = ( @@ -125,112 +119,25 @@ async function startHTTPServer(config: Config): Promise<{ app.use(express.static(config.staticPath)); - return startProxyServer(config, app); -} - -/** - * Creates and starts the HTTP and proxy servers. - * @param config Server configuration. - * @param app Express app. - * @returns Returns both the app and server configured and - * listening. - */ -async function startProxyServer( - config: Config, - app: Express, -): Promise<{ - app: Express; - server: http.Server; - socket: WebSocketServer; - readyForIncomingConnections: ReadyForConnections; -}> { const server = http.createServer(app); - const socket = addWebsocket(server, config); - - // For now, we only support domain socket access on POSIX-like systems. - // On Windows, a proxy is not created and the server starts - // listening at the specified port. - if (os.platform() === 'win32') { - if (!config.tcp) { - console.warn( - 'No port was supplied and domain socket access is not available for non-POSIX systems, falling back to TCP', - ); - } - return new Promise((resolve) => { - console.log(`Starting server on http://localhost:${config.port}`); - const readyForIncomingConnections = ( - serverImpl: FlipperServerImpl, - companionEnv: FlipperServerCompanionEnv, - ): Promise => { - attachSocketServer(socket, serverImpl, companionEnv); - return new Promise((resolve) => { - server.listen(config.port, undefined, () => resolve()); - }); - }; - resolve({app, server, socket, readyForIncomingConnections}); - }); - } - - const socketPath = await makeSocketPath(); - if (await checkSocketInUse(socketPath)) { - console.warn( - `Cannot start flipper-server because socket ${socketPath} is in use.`, - ); - tracker.track('server-socket-already-in-use', {}); - } else { - console.info(`Cleaning up stale socket ${socketPath}`); - await fs.rm(socketPath, {force: true}); - } - - const proxyServer: proxy | undefined = config.tcp - ? proxy.createProxyServer({ - target: {host: 'localhost', port: 0, socketPath}, - autoRewrite: true, - ws: true, - }) - : undefined; - - console.log('Starting socket server on ', socketPath); - if (proxyServer) { - console.log(`Starting proxy server on http://localhost:${config.port}`); - } + const socket = attachWS(server, config); exitHook(() => { console.log('Shutdown server'); - proxyServer?.close(); server.close(); - - console.log('Cleaning up socket on exit:', socketPath); - // This *must* run synchronously and we're not blocking any UI loop by definition. - // eslint-disable-next-line node/no-sync - fs.rmSync(socketPath, {force: true}); - }); - - proxyServer?.on('error', (err, _req, _res) => { - console.warn('Error in proxy server:', err); - tracker.track('server-proxy-error', {error: err.message}); - - // As it stands, if the proxy fails, which is the one - // listening on the supplied TCP port, then we should exit. - // Otherwise we risk staying in an invalid state, unable - // to recover, and thus preventing us to serve incoming requests. - // Bear in mind that exiting the process will trigger the exit hook - // defined above which will clean and close the sockets. - process.exit(0); }); return new Promise((resolve) => { + console.log(`Starting server on http://localhost:${config.port}`); const readyForIncomingConnections = ( serverImpl: FlipperServerImpl, companionEnv: FlipperServerCompanionEnv, ): Promise => { attachSocketServer(socket, serverImpl, companionEnv); return new Promise((resolve) => { - proxyServer?.listen(config.port); - server.listen(socketPath, undefined, () => { + server.listen(config.port, undefined, () => { tracker.track('server-started', { port: config.port, - tcp: config.tcp, }); resolve(); }); @@ -247,7 +154,7 @@ async function startProxyServer( * incoming connections origin. * @returns Returns the created WS. */ -function addWebsocket(server: http.Server, config: Config) { +function attachWS(server: http.Server, config: Config) { const localhost = 'localhost'; const localhostIPV4 = `localhost:${config.port}`; const localhostIPV6 = `[::1]:${config.port}`; @@ -275,8 +182,6 @@ function addWebsocket(server: http.Server, config: Config) { // No origin header? The request is not originating from a browser, so should be OK to pass through // If origin matches our own address, it means we are serving the page. - // Need the token or know that is UDS. - return process.env.SKIP_TOKEN_VERIFICATION ? true : verifyAuthToken(req); } else { // For now we don't allow cross origin request, so that an arbitrary website cannot try to @@ -299,10 +204,8 @@ function addWebsocket(server: http.Server, config: Config) { const options: ServerOptions = { noServer: true, maxPayload: WEBSOCKET_MAX_MESSAGE_SIZE, + verifyClient, }; - if (config.tcp) { - options.verifyClient = verifyClient; - } const wss = new WebSocketServer(options); server.on('upgrade', function upgrade(request, socket, head) { diff --git a/desktop/flipper-server-core/src/server/utilities.tsx b/desktop/flipper-server-core/src/server/utilities.tsx index 3ef9822f391..2ff26024cbd 100644 --- a/desktop/flipper-server-core/src/server/utilities.tsx +++ b/desktop/flipper-server-core/src/server/utilities.tsx @@ -39,63 +39,3 @@ export async function checkPortInUse(port: number): Promise { .listen(port); }); } - -/** - * Checks if a socket is in used for given path. - * If the path doesn't exist then is not in use. If it does, - * create a socket client and attempt to connect to it. - * If the connection is established, then there's a process - * already listening. Otherwise, it kind of indicates the - * contrary. - * @param path Path used instead of port number. - * @returns True or false dependning on whether the socket is in - * use or not. - */ -export async function checkSocketInUse(path: string): Promise { - if (!(await fs.pathExists(path))) { - return false; - } - return new Promise((resolve, _reject) => { - const client = net - .createConnection(path, () => { - resolve(true); - client.destroy(); - }) - .on('error', (e) => { - if (e.message.includes('ECONNREFUSED')) { - resolve(false); - } else { - console.warn( - `[conn] Socket ${path} is in use, but we don't know why.`, - e, - ); - resolve(false); - } - client.destroy(); - }); - }); -} - -/** - * Creates a socket path. Used to open the socket at location. - * Format: flipper-server-${userInfo}.sock - * @returns The created socket path. - */ -export async function makeSocketPath(): Promise { - const runtimeDir = xdgBasedir.runtime || '/tmp'; - await fs.mkdirp(runtimeDir); - const filename = `flipper-server-${os.userInfo().uid}.sock`; - const path = `${runtimeDir}/${filename}`; - - // Depending on the OS this is between 104 and 108: - // https://unix.stackexchange.com/a/367012/10198 - if (path.length >= 104) { - console.warn( - 'Ignoring XDG_RUNTIME_DIR as it would exceed the total limit for domain socket paths. See man 7 unix.', - ); - // Even with the INT32_MAX userid, we should have plenty of room. - return `/tmp/${filename}`; - } - - return path; -} diff --git a/desktop/flipper-ui-core/src/fb-stubs/ScribeLogger.tsx b/desktop/flipper-server-core/src/sessionId.tsx similarity index 55% rename from desktop/flipper-ui-core/src/fb-stubs/ScribeLogger.tsx rename to desktop/flipper-server-core/src/sessionId.tsx index 325042c644d..4df6f10205d 100644 --- a/desktop/flipper-ui-core/src/fb-stubs/ScribeLogger.tsx +++ b/desktop/flipper-server-core/src/sessionId.tsx @@ -7,12 +7,6 @@ * @format */ -export type ScribeMessage = { - category: string; - message: string; -}; +import {uuid} from 'flipper-common'; -export default class ScribeLogger { - constructor() {} - send(_message: ScribeMessage) {} -} +export const sessionId = uuid(); diff --git a/desktop/flipper-server-core/src/tracker.tsx b/desktop/flipper-server-core/src/tracker.tsx index 72e43eaf3ef..f694cec536e 100644 --- a/desktop/flipper-server-core/src/tracker.tsx +++ b/desktop/flipper-server-core/src/tracker.tsx @@ -36,7 +36,7 @@ type ServerBootstrapPerformancePayload = { type TrackerEvents = { 'server-bootstrap-performance': ServerBootstrapPerformancePayload; - 'server-started': {port: number; tcp: boolean}; + 'server-started': {port: number}; 'server-auth-token-verification': { successful: boolean; present: boolean; diff --git a/desktop/flipper-server-core/src/utils/keytar.tsx b/desktop/flipper-server-core/src/utils/keytar.tsx index 9b569b53629..cc8b098581c 100644 --- a/desktop/flipper-server-core/src/utils/keytar.tsx +++ b/desktop/flipper-server-core/src/utils/keytar.tsx @@ -13,9 +13,13 @@ import {UserNotSignedInError} from 'flipper-common'; export const SERVICE_FLIPPER = 'flipper.oAuthToken'; export type KeytarModule = { - getPassword(service: string, username: string): string; - deletePassword(service: string, username: string): void; - setPassword(service: string, username: string, password: string): void; + getPassword(service: string, username: string): Promise; + deletePassword(service: string, username: string): Promise; + setPassword( + service: string, + username: string, + password: string, + ): Promise; }; export class KeytarManager { diff --git a/desktop/flipper-server/package.json b/desktop/flipper-server/package.json index 0bf3714f54b..cb6775428e0 100644 --- a/desktop/flipper-server/package.json +++ b/desktop/flipper-server/package.json @@ -15,18 +15,18 @@ "file-stream-rotator": "^0.6.1", "flipper-common": "0.0.0", "flipper-pkg-lib": "0.0.0", + "flipper-server-client": "0.0.0", "flipper-server-companion": "0.0.0", "flipper-server-core": "0.0.0", - "flipper-server-client": "0.0.0", - "fs-extra": "^11.1.0", + "fs-extra": "^11.1.1", "http-proxy": "^1.18.1", "metro": "^0.70.2", "open": "^8.3.0", "p-filter": "^2.1.0", - "ws": "8.8.0", "reconnecting-websocket": "^4.4.0", + "ws": "8.13.0", "xdg-basedir": "^4", - "yargs": "^17.6.2" + "yargs": "^17.7.2" }, "devDependencies": { "@types/express": "^4.17.13", diff --git a/desktop/flipper-server/src/index.tsx b/desktop/flipper-server/src/index.tsx index 482ffc81a42..5a2ba8ceba7 100644 --- a/desktop/flipper-server/src/index.tsx +++ b/desktop/flipper-server/src/index.tsx @@ -74,12 +74,6 @@ const argv = yargs type: 'boolean', default: true, }, - tcp: { - describe: - 'Open a TCP port (--no-tcp can be specified as to use unix-domain-socket exclusively)', - type: 'boolean', - default: true, - }, replace: { describe: 'Replaces any running instance, if any.', type: 'boolean', @@ -150,10 +144,17 @@ async function shutdown() { } async function start() { - console.info('[flipper-server][bootstrap] Booting up'); const t0 = performance.now(); - const enhanceLogger = await initializeLogger(staticPath); + const isProduction = + process.env.NODE_ENV !== 'development' && process.env.NODE_ENV !== 'test'; + const environmentInfo = await getEnvironmentInfo( + rootPath, + isProduction, + true, + ); + + await initializeLogger(environmentInfo, staticPath); const t1 = performance.now(); const loggerInitializedMS = t1 - t0; @@ -186,15 +187,6 @@ async function start() { `[flipper-server][bootstrap] Keytar loaded (${keytarLoadedMS} ms)`, ); - const isProduction = - process.env.NODE_ENV !== 'development' && process.env.NODE_ENV !== 'test'; - - const environmentInfo = await getEnvironmentInfo( - rootPath, - isProduction, - true, - ); - if (await checkPortInUse(argv.port)) { console.warn(`[flipper-server] Port ${argv.port} is already in use`); if (!argv.replace) { @@ -214,7 +206,6 @@ async function start() { staticPath, entry: `index.web${argv.bundler ? '.dev' : ''}.html`, port: argv.port, - tcp: argv.tcp, }); const t4 = performance.now(); @@ -244,10 +235,6 @@ async function start() { await flipperServer.close(); }); - enhanceLogger((logEntry) => { - flipperServer.emit('server-log', logEntry); - }); - const companionEnv = await initCompanionEnv(flipperServer); const t6 = performance.now(); @@ -308,10 +295,6 @@ async function start() { } async function launch() { - if (!argv.tcp) { - return; - } - let token: string | undefined; if (await hasAuthToken()) { token = await getAuthToken(); diff --git a/desktop/flipper-server/src/logger.tsx b/desktop/flipper-server/src/logger.tsx index ed1d6469ad4..14b4c3b90c0 100644 --- a/desktop/flipper-server/src/logger.tsx +++ b/desktop/flipper-server/src/logger.tsx @@ -9,11 +9,11 @@ import path from 'path'; import { + addLogTailer, + EnvironmentInfo, LoggerExtractError, LoggerFormat, - LoggerInfo, LoggerTypes, - Logger, setLoggerInstance, } from 'flipper-common'; // @ts-expect-error @@ -21,81 +21,21 @@ import fsRotator from 'file-stream-rotator'; import {ensureFile} from 'fs-extra'; import {access} from 'fs/promises'; import {constants} from 'fs'; +import {initializeLogger as initLogger} from 'flipper-server-core'; export const loggerOutputFile = 'flipper-server-log.out'; -const logTypes: LoggerTypes[] = ['debug', 'info', 'warn', 'error']; - -function createLogger(): Logger { - return { - track(..._args: [any, any, any?, any?]) { - // TODO: only if verbose console.debug(...args); - // console.warn('(skipper track)', args); - }, - trackTimeSince(..._args: [any, any, any?]) { - // TODO: only if verbose console.debug(...args); - // console.warn('(skipped trackTimeSince)', args); - }, - debug(...args: any[]) { - console.debug(...args); - }, - error(...args: any[]) { - console.error(...args); - }, - warn(...args: any[]) { - console.warn(...args); - }, - info(...args: any[]) { - console.info(...args); - }, - }; -} - -type FlipperLogProxy = (entry: LoggerInfo) => void; - -const consoleProxy = (proxy: FlipperLogProxy) => { - function log(level: LoggerTypes, ...data: Array): void { - const logInfo = LoggerFormat(level, ...data); - proxy(logInfo); - - if (level === 'error') { - const { - message, - error: {stack, interaction, name}, - } = LoggerExtractError(data); - const logInfo = LoggerFormat(level, { - name, - stack, - interaction, - message, - }); - proxy(logInfo); - } - } - - for (const method of logTypes) { - const originalConsole: {[key: string]: any} = console; - const originalMethod = originalConsole[method]; - const overrideMethod = (...args: Array) => { - const result = originalMethod(...args); - log(method, ...args); - return result; - }; - originalConsole[method] = overrideMethod; - } -}; - -export async function initializeLogger(staticDir: string) { +export async function initializeLogger( + environmentInfo: EnvironmentInfo, + staticDir: string, +) { // Suppress stdout debug messages, but keep writing them to the file. console.debug = function () {}; - const logger = createLogger(); + const logger = initLogger(environmentInfo); setLoggerInstance(logger); - let onConsoleEntry: ((entry: LoggerInfo) => void) | undefined; - const logFilename = path.join(staticDir, loggerOutputFile); - let logStream: NodeJS.WriteStream | undefined = undefined; try { await ensureFile(logFilename); @@ -112,12 +52,22 @@ export async function initializeLogger(staticDir: string) { console.warn('initializeLogger -> cannot write logs to FS', e); } - consoleProxy((entry: LoggerInfo) => { - logStream?.write(`${JSON.stringify(entry)}\n`); - onConsoleEntry?.(entry); - }); + addLogTailer((level: LoggerTypes, ...data: Array) => { + const logInfo = LoggerFormat(level, ...data); + logStream?.write(`${JSON.stringify(logInfo)}\n`); - return (newOnConsoleEntry: (entry: LoggerInfo) => void) => { - onConsoleEntry = newOnConsoleEntry; - }; + if (level === 'error') { + const { + message, + error: {stack, interaction, name}, + } = LoggerExtractError(data); + const logInfo = LoggerFormat(level, { + name, + stack, + interaction, + message, + }); + logStream?.write(`${JSON.stringify(logInfo)}\n`); + } + }); } diff --git a/desktop/flipper-ui-browser/package.json b/desktop/flipper-ui-browser/package.json index 70e146da5e0..6e25ac516fc 100644 --- a/desktop/flipper-ui-browser/package.json +++ b/desktop/flipper-ui-browser/package.json @@ -11,6 +11,7 @@ "bugs": "https://github.com/facebook/flipper/issues", "dependencies": { "file-saver": "^2.0.5", + "js-base64": "^3.7.5", "reconnecting-websocket": "^4.4.0" }, "devDependencies": { diff --git a/desktop/flipper-ui-browser/src/HMRClient.tsx b/desktop/flipper-ui-browser/src/HMRClient.tsx index f4de7d9b199..ad76b730e69 100644 --- a/desktop/flipper-ui-browser/src/HMRClient.tsx +++ b/desktop/flipper-ui-browser/src/HMRClient.tsx @@ -270,7 +270,7 @@ function showCompileError() { // Symbolicating compile errors is wasted effort // because the stack trace is meaningless: (error as any).preventSymbolication = true; - window.flipperShowError?.(message); + window.flipperShowMessage?.(message); throw error; } diff --git a/desktop/flipper-ui-browser/src/global.tsx b/desktop/flipper-ui-browser/src/global.tsx index f927c0c4b4b..21158a317ee 100644 --- a/desktop/flipper-ui-browser/src/global.tsx +++ b/desktop/flipper-ui-browser/src/global.tsx @@ -17,7 +17,8 @@ declare global { debug: boolean; }; - flipperShowError?(error: string): void; - flipperHideError?(): void; + flipperShowMessage?(message: string): void; + flipperHideMessage?(): void; + flipperShowNoConnection?(): void; } } diff --git a/desktop/flipper-ui-browser/src/index.tsx b/desktop/flipper-ui-browser/src/index.tsx index 06b79d61b7f..11e9837fc64 100644 --- a/desktop/flipper-ui-browser/src/index.tsx +++ b/desktop/flipper-ui-browser/src/index.tsx @@ -16,6 +16,9 @@ if (loadingContainer) { loadingContainer.innerText = 'Loading...'; } +let cachedFile: {name: string; data: string} | undefined; +let cachedDeepLinkURL: string | undefined; + async function start() { // @ts-ignore electronRequire = function (path: string) { @@ -38,6 +41,23 @@ async function start() { token = manifest.token; } + const openPlugin = params.get('open-plugin'); + if (openPlugin) { + function removePrefix(input: string, prefix: string): string { + const regex = new RegExp(`^${prefix}+`); + return input.replace(regex, ''); + } + + const url = new URL(openPlugin); + const maybeParams = removePrefix(url.pathname, '/'); + const params = new URLSearchParams(maybeParams); + + const deeplinkURL = new URL('flipper://open-plugin'); + deeplinkURL.search = params.toString(); + + cachedDeepLinkURL = deeplinkURL.toString(); + } + const searchParams = new URLSearchParams({token: token ?? ''}); const flipperServer = await createFlipperServer( @@ -47,13 +67,13 @@ async function start() { (state: FlipperServerState) => { switch (state) { case FlipperServerState.CONNECTING: - window.flipperShowError?.('Connecting to server...'); + window.flipperShowMessage?.('Connecting to server...'); break; case FlipperServerState.CONNECTED: - window?.flipperHideError?.(); + window?.flipperHideMessage?.(); break; case FlipperServerState.DISCONNECTED: - window?.flipperShowError?.('Lost connection to server'); + window?.flipperShowNoConnection?.(); break; } }, @@ -71,24 +91,108 @@ async function start() { const flipperServerConfig = await flipperServer.exec('get-config'); initializeRenderHost(flipperServer, flipperServerConfig); + initializePWA(); // By turning this in a require, we force the JS that the body of this module (init) has completed (initializeElectron), // before starting the rest of the Flipper process. // This prevent issues where the render host is referred at module initialisation level, // but not set yet, which might happen when using normal imports. // TODO: remove - window.flipperShowError?.('Connected to Flipper Server successfully'); + window.flipperShowMessage?.('Connected to Flipper Server successfully'); + // @ts-ignore // eslint-disable-next-line import/no-commonjs require('flipper-ui-core').startFlipperDesktop(flipperServer); - window.flipperHideError?.(); + window.flipperHideMessage?.(); } start().catch((e) => { console.error('Failed to start flipper-ui-browser', e); - window.flipperShowError?.('Failed to start flipper-ui-browser: ' + e); + window.flipperShowMessage?.('Failed to start flipper-ui-browser: ' + e); }); +async function initializePWA() { + console.log('[PWA] Initialization'); + + let rehydrated = false; + const openFileIfAny = () => { + if (!cachedFile || !rehydrated) { + return; + } + window.dispatchEvent( + new CustomEvent('open-flipper-file', { + detail: [cachedFile.name, cachedFile.data], + }), + ); + cachedFile = undefined; + }; + + const openURLIfAny = () => { + if (!cachedDeepLinkURL || !rehydrated) { + return; + } + window.dispatchEvent( + new CustomEvent('flipper-protocol-handler', { + detail: [cachedDeepLinkURL], + }), + ); + cachedDeepLinkURL = undefined; + }; + + if ('serviceWorker' in navigator) { + navigator.serviceWorker + .register('/service-worker.js') + .then(() => { + console.log('[PWA] Service Worker has been registered'); + }) + .catch((e) => { + console.error('[PWA] failed to register Service Worker', e); + }); + } + + if ('launchQueue' in window) { + console.log('[PWA] File Handling API is supported'); + + // @ts-ignore + window.launchQueue.setConsumer(async (launchParams) => { + if (!launchParams || !launchParams.files) { + return; + } + console.log('[PWA] Attempt to to open a file'); + for (const file of launchParams.files) { + const blob = await file.getFile(); + blob.handle = file; + + const data = await blob.text(); + const name = file.name; + + cachedFile = {name, data}; + + openFileIfAny(); + } + }); + } else { + console.warn('[PWA] File Handling API is not supported'); + } + + console.log('[PWA] Add before install prompt listener'); + window.addEventListener('beforeinstallprompt', (e) => { + // Prevent Chrome 67 and earlier from automatically showing the prompt. + e.preventDefault(); + // Stash the event so it can be triggered later. + // @ts-ignore + global.PWAppInstallationEvent = e; + console.log('[PWA] Installation event has been captured'); + }); + + window.addEventListener('storeRehydrated', () => { + console.info('[PWA] Store is rehydrated'); + rehydrated = true; + openFileIfAny(); + openURLIfAny(); + }); +} + // getLogger() is not yet created when the electron app starts. // we can't create it here yet, as the real logger is wired up to // the redux store and the rest of the world. So we create a delegating logger diff --git a/desktop/flipper-ui-browser/src/initializeRenderHost.tsx b/desktop/flipper-ui-browser/src/initializeRenderHost.tsx index 1f576144269..3e82cc1ce5b 100644 --- a/desktop/flipper-ui-browser/src/initializeRenderHost.tsx +++ b/desktop/flipper-ui-browser/src/initializeRenderHost.tsx @@ -11,11 +11,14 @@ import { FlipperServer, FlipperServerConfig, isProduction, + uuid, wrapRequire, } from 'flipper-common'; import type {RenderHost} from 'flipper-ui-core'; import FileSaver from 'file-saver'; +import {Base64} from 'js-base64'; + declare module globalThis { let require: any; } @@ -31,6 +34,13 @@ globalThis.require = wrapRequire((module: string) => { ); }); +type FileEncoding = 'utf-8' | 'base64' | 'binary'; +interface FileDescriptor { + data: string | Uint8Array | undefined; + name: string; + encoding: FileEncoding; +} + export function initializeRenderHost( flipperServer: FlipperServer, flipperServerConfig: FlipperServerConfig, @@ -42,8 +52,83 @@ export function initializeRenderHost( writeTextToClipboard(text: string) { return navigator.clipboard.writeText(text); }, - async importFile() { - throw new Error('Not implemented'); + async importFile(options?: { + defaultPath?: string; + extensions?: string[]; + title?: string; + encoding?: FileEncoding; + multi?: false; + }) { + return new Promise( + (resolve, reject) => { + try { + let selectionMade = false; + + const fileInput = document.createElement('input'); + fileInput.type = 'file'; + fileInput.id = uuid(); + if (options?.extensions) { + fileInput.accept = options?.extensions.join(', '); + } + fileInput.multiple = options?.multi ?? false; + + fileInput.addEventListener('change', async (event) => { + selectionMade = true; + const target = event.target as HTMLInputElement | undefined; + if (!target || !target.files) { + resolve(undefined); + return; + } + + const files: File[] = Array.from(target.files); + const descriptors: FileDescriptor[] = await Promise.all( + files.map(async (file) => { + switch (options?.encoding) { + case 'base64': { + const bytes = new Uint8Array(await file.arrayBuffer()); + const base64Content = Base64.fromUint8Array(bytes); + return { + data: base64Content, + name: file.name, + encoding: 'base64', + }; + } + case 'binary': + return { + data: new Uint8Array(await file.arrayBuffer()), + name: file.name, + encoding: 'binary', + }; + default: + return { + data: await file.text(), + name: file.name, + encoding: 'utf-8', + }; + } + }), + ); + resolve(options?.multi ? descriptors : descriptors[0]); + }); + + window.addEventListener( + 'focus', + () => { + setTimeout(() => { + if (!selectionMade) { + resolve(undefined); + } + }, 300); + }, + {once: true}, + ); + + fileInput.click(); + } catch (error) { + reject(error); + } + }, + ); }, async exportFile(data: string, {defaultPath}: {defaultPath?: string}) { const file = new File([data], defaultPath ?? 'unknown', { @@ -68,11 +153,13 @@ export function initializeRenderHost( hasFocus() { return document.hasFocus(); }, - onIpcEvent(_event) { - // no-op + onIpcEvent(event, cb) { + window.addEventListener(event as string, (ev) => { + cb(...((ev as CustomEvent).detail as any)); + }); }, - sendIpcEvent(_event, ..._args: any[]) { - // no-op + sendIpcEvent(event, ...args: any[]) { + window.dispatchEvent(new CustomEvent(event, {detail: args})); }, shouldUseDarkColors() { return !!( @@ -82,7 +169,7 @@ export function initializeRenderHost( ); }, restartFlipper() { - window.flipperShowError?.( + window.flipperShowMessage?.( 'Flipper settings have changed, please restart flipper server for the changes to take effect', ); }, diff --git a/desktop/flipper-ui-core/package.json b/desktop/flipper-ui-core/package.json index e7abb52701b..70e3060eeb7 100644 --- a/desktop/flipper-ui-core/package.json +++ b/desktop/flipper-ui-core/package.json @@ -17,15 +17,15 @@ "@tanishiking/aho-corasick": "^0.0.1", "antd": "4.19.2", "cbuffer": "^2.2.0", + "deep-equal": "^2.2.2", "@nicksrandall/console-feed": "^3.5.0", - "deep-equal": "^2.2.1", "eventemitter3": "^4.0.7", "flipper-client-sdk": "^0.0.3", "flipper-common": "0.0.0", "flipper-frontend-core": "0.0.0", "flipper-plugin": "0.0.0", "flipper-ui-core": "0.0.0", - "hotkeys-js": "^3.9.3", + "hotkeys-js": "^3.12.0", "immer": "^9.0.18", "js-base64": "^3.7.5", "jszip": "^3.10.1", @@ -42,18 +42,18 @@ "react-player": "^2.11.0", "react-redux": "^7.2.6", "react-test-renderer": "^0.0.0-experimental-2bf7c02f0-20220314", - "react-virtualized-auto-sizer": "^1.0.7", - "react-window": "^1.8.6", - "redux": "^4.1.2", + "react-virtualized-auto-sizer": "1.0.7", + "react-window": "^1.8.9", + "redux": "^4.2.1", "redux-persist": "^6.0.0", - "reselect": "^4.1.7", - "semver": "^7.3.7", + "reselect": "^4.1.8", + "semver": "^7.5.4", "uuid": "^8.3.2" }, "devDependencies": { "@testing-library/dom": "^8.20.0", "@types/deep-equal": "^1.0.1", - "@types/jest": "^29.5.1", + "@types/jest": "^29.5.3", "@types/lodash.memoize": "^4.1.7", "@types/react": "^17.0.39", "@types/react-dom": "^17.0.12", diff --git a/desktop/flipper-ui-core/src/chrome/ConsoleLogs.tsx b/desktop/flipper-ui-core/src/chrome/ConsoleLogs.tsx index 65766907c26..ee7911ca79a 100644 --- a/desktop/flipper-ui-core/src/chrome/ConsoleLogs.tsx +++ b/desktop/flipper-ui-core/src/chrome/ConsoleLogs.tsx @@ -20,7 +20,7 @@ import {Button, Dropdown, Menu, Checkbox} from 'antd'; import {DownOutlined} from '@ant-design/icons'; import {DeleteOutlined} from '@ant-design/icons'; import CBuffer from 'cbuffer'; -import {addLogTailer} from '../consoleLogTailer'; +import {addLogTailer} from 'flipper-common'; import {v4} from 'uuid'; const MAX_DISPLAY_LOG_ITEMS = 1000; diff --git a/desktop/flipper-ui-core/src/chrome/SettingsSheet.tsx b/desktop/flipper-ui-core/src/chrome/SettingsSheet.tsx index a4719734723..b75e23bc2ed 100644 --- a/desktop/flipper-ui-core/src/chrome/SettingsSheet.tsx +++ b/desktop/flipper-ui-core/src/chrome/SettingsSheet.tsx @@ -432,11 +432,7 @@ class SettingsSheet extends Component { process listening at port 52342. See below:
- - sudo lsof -i :52342 -
- sudo kill <PID> -
+ sudo kill $(lsof -t -i :52342) ) : ( <> diff --git a/desktop/flipper-ui-core/src/chrome/ShareSheetExportFile.tsx b/desktop/flipper-ui-core/src/chrome/ShareSheetExportFile.tsx index ded73c4acaf..0e997469e4a 100644 --- a/desktop/flipper-ui-core/src/chrome/ShareSheetExportFile.tsx +++ b/desktop/flipper-ui-core/src/chrome/ShareSheetExportFile.tsx @@ -13,15 +13,16 @@ import {reportPlatformFailures} from 'flipper-common'; import {Logger} from 'flipper-common'; import {IdlerImpl} from '../utils/Idler'; import { - exportStoreToFile, EXPORT_FLIPPER_TRACE_EVENT, displayFetchMetadataErrors, + exportStore, } from '../utils/exportData'; import ShareSheetErrorList from './ShareSheetErrorList'; import ShareSheetPendingDialog from './ShareSheetPendingDialog'; import {ReactReduxContext, ReactReduxContextValue} from 'react-redux'; import {MiddlewareAPI} from '../reducers/index'; import {Modal} from 'antd'; +import {getRenderHostInstance} from 'flipper-frontend-core'; const Container = styled(FlexColumn)({ padding: 20, @@ -47,7 +48,6 @@ const InfoText = styled(Text)({ type Props = { onHide: () => void; - file: string; logger: Logger; }; @@ -88,27 +88,25 @@ export default class ShareSheetExportFile extends Component { const mark = 'shareSheetExportFile'; performance.mark(mark); try { - if (!this.props.file) { - return; - } - const {fetchMetaDataErrors} = await reportPlatformFailures( - exportStoreToFile( - this.props.file, - this.store, - false, - this.idler, - (msg: string) => { + const {serializedString, fetchMetaDataErrors} = + await reportPlatformFailures( + exportStore(this.store, false, this.idler, (msg: string) => { this.setState({statusUpdate: msg}); - }, - ), - `${EXPORT_FLIPPER_TRACE_EVENT}:UI_FILE`, - ); + }), + `${EXPORT_FLIPPER_TRACE_EVENT}:UI_FILE`, + ); this.setState({ fetchMetaDataErrors, result: fetchMetaDataErrors ? {error: JSON.stringify(fetchMetaDataErrors) as any, kind: 'error'} : {kind: 'success'}, }); + + await getRenderHostInstance().exportFile(serializedString, { + defaultPath: 'export.flipper', + encoding: 'utf-8', + }); + this.props.logger.trackTimeSince(mark, 'export:file-success'); } catch (err) { const result: { diff --git a/desktop/flipper-ui-core/src/chrome/plugin-manager/PluginPackageInstaller.tsx b/desktop/flipper-ui-core/src/chrome/plugin-manager/PluginPackageInstaller.tsx index 7295494e3a0..d76133d8e6b 100644 --- a/desktop/flipper-ui-core/src/chrome/plugin-manager/PluginPackageInstaller.tsx +++ b/desktop/flipper-ui-core/src/chrome/plugin-manager/PluginPackageInstaller.tsx @@ -43,17 +43,20 @@ export default function PluginPackageInstaller({ }: { onInstall: () => Promise; }) { - const [path, setPath] = useState(''); + const [content, setContent] = useState(); const [isPathValid, setIsPathValid] = useState(false); const [error, setError] = useState(); const [inProgress, setInProgress] = useState(false); const onClick = async () => { + if (!content) { + return; + } setError(undefined); setInProgress(true); try { - await getRenderHostInstance().flipperServer!.exec( - 'plugins-install-from-file', - path, + await getRenderHostInstance().flipperServer?.exec( + 'plugins-install-from-content', + content, ); await onInstall(); } catch (e) { @@ -83,13 +86,13 @@ export default function PluginPackageInstaller({ { + encoding="base64" + onChange={async (newFile) => { if (newFile) { - // TODO: Fix me before implementing Browser Flipper. "path" is only availbale in Electron! - setPath(newFile.path!); + setContent(newFile.data as string); setIsPathValid(true); } else { - setPath(''); + setContent(undefined); setIsPathValid(false); } setError(undefined); diff --git a/desktop/flipper-ui-core/src/dispatcher/application.tsx b/desktop/flipper-ui-core/src/dispatcher/application.tsx index 903443ca2fc..936b23e6178 100644 --- a/desktop/flipper-ui-core/src/dispatcher/application.tsx +++ b/desktop/flipper-ui-core/src/dispatcher/application.tsx @@ -10,7 +10,7 @@ import {Store} from '../reducers/index'; import {Logger} from 'flipper-common'; import { - importFileToStore, + importDataToStore, IMPORT_FLIPPER_TRACE_EVENT, } from '../utils/exportData'; import {tryCatchReportPlatformFailures} from 'flipper-common'; @@ -67,9 +67,9 @@ export default (store: Store, logger: Logger) => { }); }); - renderHost.onIpcEvent('open-flipper-file', (url: string) => { + renderHost.onIpcEvent('open-flipper-file', (name: string, data: string) => { tryCatchReportPlatformFailures(() => { - return importFileToStore(url, store); + return importDataToStore(name, data, store); }, `${IMPORT_FLIPPER_TRACE_EVENT}:Deeplink`); }); }; diff --git a/desktop/flipper-ui-core/src/dispatcher/flipperServer.tsx b/desktop/flipper-ui-core/src/dispatcher/flipperServer.tsx index 0afb35618bc..a9692b4df49 100644 --- a/desktop/flipper-ui-core/src/dispatcher/flipperServer.tsx +++ b/desktop/flipper-ui-core/src/dispatcher/flipperServer.tsx @@ -182,7 +182,7 @@ function handleServerStateChange({ error?: string; }) { if (state === 'error') { - console.warn(`[conn] Flipper server state -> ${state}`, error); + console.warn(`Flipper server state -> ${state}`, error); if (error?.includes('EADDRINUSE')) { handeEADDRINUSE(error); } else { @@ -194,7 +194,7 @@ function handleServerStateChange({ }); } } else { - console.info(`[conn] Flipper server state -> ${state}`); + console.info(`Flipper server state -> ${state}`); } } @@ -210,7 +210,7 @@ function handeEADDRINUSE(errorMessage: string) {

Please try to kill the offending process by running{' '} - kill $(lsof -ti:PORTNUMBER) and restart flipper. + sudo kill $(lsof -ti:PORTNUMBER) and restart flipper.

{errorMessage} @@ -348,14 +348,14 @@ export async function handleClientConnected( } console.log( - `[conn] Searching matching device ${query.device_id} for client ${query.app}...`, + `Searching matching device ${query.device_id} for client ${query.app}...`, ); const device = getDeviceBySerial(store.getState(), query.device_id) ?? (await findDeviceForConnection(store, query.app, query.device_id).catch( (e) => { console.warn( - `[conn] Failed to find device '${query.device_id}' while connection app '${query.app}'`, + `Failed to find device '${query.device_id}' while connection app '${query.app}'`, e, ); const key = `device-find-failure-${query.device_id}`; @@ -408,19 +408,17 @@ export async function handleClientConnected( await timeout( 30 * 1000, client.init(), - `[conn] Failed to initialize client ${query.app} on ${query.device_id} in a timely manner`, - ); - console.log( - `[conn] ${query.app} on ${query.device_id} connected and ready.`, + `Failed to initialize client ${query.app} on ${query.device_id} in a timely manner`, ); + console.log(`${query.app} on ${query.device_id} connected and ready.`); } catch (e) { if (e instanceof NoLongerConnectedToClientError) { console.warn( - `[conn] Client ${query.app} on ${query.device_id} disconnected while initialising`, + `Client ${query.app} on ${query.device_id} disconnected while initialising`, ); return; } - console.warn(`[conn] Failed to handle client connected: ${e}`); + console.warn(`Failed to handle client connected: ${e}`); } } @@ -465,7 +463,7 @@ async function findDeviceForConnection( (device) => device.serial === serial, ); if (matchingDevice) { - console.log(`[conn] Found device for: ${clientId} on ${serial}.`); + console.log(`Found device for: ${clientId} on ${serial}.`); clearTimeout(timeout); resolve(matchingDevice); unsubscribe(); diff --git a/desktop/flipper-ui-core/src/dispatcher/index.tsx b/desktop/flipper-ui-core/src/dispatcher/index.tsx index 1e9090b38b4..ebd445f2f96 100644 --- a/desktop/flipper-ui-core/src/dispatcher/index.tsx +++ b/desktop/flipper-ui-core/src/dispatcher/index.tsx @@ -26,7 +26,10 @@ import {Store} from '../reducers/index'; import {Dispatcher} from './types'; import {notNull} from '../utils/typeUtils'; -export default function (store: Store, logger: Logger): () => Promise { +export default async function ( + store: Store, + logger: Logger, +): Promise<() => Promise> { // This only runs in development as when the reload // kicks in it doesn't unregister the shortcuts const dispatchers: Array = [ @@ -43,10 +46,11 @@ export default function (store: Store, logger: Logger): () => Promise { pluginChangeListener, pluginsSourceUpdateListener, ].filter(notNull); - const globalCleanup = dispatchers - .map((dispatcher) => dispatcher(store, logger)) - .filter(Boolean); - return () => { - return Promise.all(globalCleanup).then(() => {}); + const globalCleanup = await Promise.all( + dispatchers.map((dispatcher) => dispatcher(store, logger)).filter(Boolean), + ); + + return async () => { + await Promise.all(globalCleanup); }; } diff --git a/desktop/flipper-ui-core/src/fb-stubs/ErrorReporter.tsx b/desktop/flipper-ui-core/src/fb-stubs/ErrorReporter.tsx index 77fbc283aec..299bd99f7cc 100644 --- a/desktop/flipper-ui-core/src/fb-stubs/ErrorReporter.tsx +++ b/desktop/flipper-ui-core/src/fb-stubs/ErrorReporter.tsx @@ -13,7 +13,7 @@ * so that all logged errors get reported to this class. */ export function cleanStack(_stack: string, _loc?: string) {} -import ScribeLogger from './ScribeLogger'; +import {ScribeLogger} from 'flipper-common'; export default class ErrorReporter { constructor(_scribeLogger: ScribeLogger) {} diff --git a/desktop/flipper-ui-core/src/fb-stubs/checkForUpdate.tsx b/desktop/flipper-ui-core/src/fb-stubs/checkForUpdate.tsx index 9d3381bdc47..48f2b700747 100644 --- a/desktop/flipper-ui-core/src/fb-stubs/checkForUpdate.tsx +++ b/desktop/flipper-ui-core/src/fb-stubs/checkForUpdate.tsx @@ -9,8 +9,7 @@ import {VersionCheckResult} from '../chrome/UpdateIndicator'; import {getRenderHostInstance} from 'flipper-frontend-core'; - -const updateServer = 'https://www.facebook.com/fbflipper/public/latest.json'; +import config from './config'; const getPlatformSpecifier = (): string => { switch (getRenderHostInstance().serverConfig.environmentInfo.os.platform) { @@ -52,7 +51,7 @@ const parseResponse = (resp: any): VersionCheckResult => { export async function checkForUpdate( currentVersion: string, ): Promise { - return fetch(`${updateServer}?version=${currentVersion}`).then( + return fetch(`${config.updateServer}?version=${currentVersion}`).then( (res: Response) => { switch (res.status) { case 204: diff --git a/desktop/flipper-ui-core/src/reducers/application.tsx b/desktop/flipper-ui-core/src/reducers/application.tsx index 5c480ffaa29..8a5957e36fe 100644 --- a/desktop/flipper-ui-core/src/reducers/application.tsx +++ b/desktop/flipper-ui-core/src/reducers/application.tsx @@ -7,7 +7,6 @@ * @format */ -import {v1 as uuidv1} from 'uuid'; import {getRenderHostInstance} from 'flipper-frontend-core'; import {Actions} from './'; @@ -44,7 +43,6 @@ export type State = { rightSidebarAvailable: boolean; windowIsFocused: boolean; share: ShareType | null; - sessionId: string | null; launcherMsg: LauncherMsg; statusMessages: Array; }; @@ -95,7 +93,6 @@ export const initialState: () => State = () => ({ windowIsFocused: getRenderHostInstance().hasFocus(), activeSheet: null, share: null, - sessionId: uuidv1(), launcherMsg: { severity: 'warning', message: '', diff --git a/desktop/flipper-ui-core/src/sandy-chrome/Navbar.tsx b/desktop/flipper-ui-core/src/sandy-chrome/Navbar.tsx index df30c244450..e84aff56fb1 100644 --- a/desktop/flipper-ui-core/src/sandy-chrome/Navbar.tsx +++ b/desktop/flipper-ui-core/src/sandy-chrome/Navbar.tsx @@ -45,11 +45,9 @@ import NetworkGraph from '../chrome/NetworkGraph'; import {errorCounterAtom} from '../chrome/ConsoleLogs'; import {filterNotifications} from './notification/notificationUtils'; import { - canFileExport, - canOpenDialog, exportEverythingEverywhereAllAtOnce, ExportEverythingEverywhereAllAtOnceStatus, - showOpenDialog, + startFileImport, startFileExport, startLinkExport, } from '../utils/exportData'; @@ -591,9 +589,9 @@ function ExtrasMenu() { () => startLinkExport(store.dispatch), [store.dispatch], ); - const startImportTracked = useTrackedCallback( + const startFileImportTracked = useTrackedCallback( 'File import', - () => showOpenDialog(store), + () => startFileImport(store), [store], ); @@ -627,16 +625,12 @@ function ExtrasMenu() { }}> Add Plugins - {canOpenDialog() ? ( - - Import Flipper file - - ) : null} - {canFileExport() ? ( - - Export Flipper file - - ) : null} + + Import Flipper file + + + Export Flipper file + {constants.ENABLE_SHAREABLE_LINK ? ( { + const persistor = persistStore(store, undefined, async () => { // Make sure process state is set before dispatchers run - dispatcher(store, logger); + await dispatcher(store, logger); + getRenderHostInstance().sendIpcEvent('storeRehydrated'); }); setPersistor(persistor); @@ -168,17 +168,17 @@ function init(flipperServer: FlipperServer) { connectFlipperServerToStore(flipperServer, store, logger); + enableConsoleHook(); + enableConnectivityHook(flipperServer); + // TODO T116224873: Return the following code back instead of ReactDOM.react when the following issue is fixed: https://github.com/react-component/trigger/issues/288 // const root = createRoot(document.getElementById('root')!); // root.render(); - ReactDOM.render( - , - document.getElementById('root')!, - ); - - enableConsoleHook(); - enableConnectivityHook(flipperServer); + const root = document.getElementById('root'); + if (root) { + ReactDOM.render(, root); + } const launcherMessage = getRenderHostInstance().serverConfig.processConfig.launcherMsg; @@ -193,8 +193,8 @@ function init(flipperServer: FlipperServer) { } } -export async function startFlipperDesktop(flipperServer: FlipperServer) { - getRenderHostInstance(); // renderHost instance should be set at this point! +export function startFlipperDesktop(flipperServer: FlipperServer) { + getRenderHostInstance(); init(flipperServer); } diff --git a/desktop/flipper-ui-core/src/utils/exportData.tsx b/desktop/flipper-ui-core/src/utils/exportData.tsx index 257a3680680..f2de950a44d 100644 --- a/desktop/flipper-ui-core/src/utils/exportData.tsx +++ b/desktop/flipper-ui-core/src/utils/exportData.tsx @@ -26,12 +26,11 @@ import {DevicePluginMap, ClientPluginMap} from '../plugin'; import {BaseDevice} from 'flipper-frontend-core'; import {ArchivedDevice} from 'flipper-frontend-core'; import {v4 as uuidv4} from 'uuid'; -import {tryCatchReportPlatformFailures} from 'flipper-common'; import {TestIdler} from './Idler'; import {processMessageQueue} from './messageQueue'; import {getPluginTitle} from './pluginUtils'; import {capture} from './screenshot'; -import {Dialog, getFlipperLib, Idler, path} from 'flipper-plugin'; +import {Dialog, getFlipperLib, Idler} from 'flipper-plugin'; import {ClientQuery} from 'flipper-common'; import ShareSheetExportUrl from '../chrome/ShareSheetExportUrl'; import ShareSheetExportFile from '../chrome/ShareSheetExportFile'; @@ -44,6 +43,7 @@ import {safeFilename} from './safeFilename'; import {getExportablePlugins} from '../selectors/connections'; import {notification} from 'antd'; import openSupportRequestForm from '../fb-stubs/openSupportRequestForm'; +import {getStore} from '../store'; export const IMPORT_FLIPPER_TRACE_EVENT = 'import-flipper-trace'; export const EXPORT_FLIPPER_TRACE_EVENT = 'export-flipper-trace'; @@ -527,7 +527,7 @@ export const exportStoreToFile = ( export async function importDataToStore( source: string, data: string, - store: Store, + store: Store = getStore(), ) { getLogger().track('usage', IMPORT_FLIPPER_TRACE_EVENT); const json: ExportType = JSON.parse(data); @@ -594,26 +594,14 @@ export const importFileToStore = async (file: string, store: Store) => { } }; -export function canOpenDialog() { - return !!getRenderHostInstance().showOpenDialog; -} - -export function showOpenDialog(store: Store) { - return getRenderHostInstance() - .showOpenDialog?.({ - filter: {extensions: ['flipper', 'json', 'txt'], name: 'Flipper files'}, - }) - .then((filePath) => { - if (filePath) { - tryCatchReportPlatformFailures(() => { - importFileToStore(filePath, store); - }, `${IMPORT_FLIPPER_TRACE_EVENT}:UI`); - } - }); -} - -export function canFileExport() { - return !!getRenderHostInstance().showSaveDialog; +export async function startFileImport(store: Store) { + const file = await getRenderHostInstance().importFile({ + extensions: ['flipper', 'json', 'txt'], + }); + if (!file || typeof file.data !== 'string') { + return; + } + importDataToStore(file.name, file.data as string, store); } async function startDeviceFlipperFolderExport() { @@ -765,25 +753,15 @@ export async function exportEverythingEverywhereAllAtOnce( } export async function startFileExport(dispatch: Store['dispatch']) { - const file = await getRenderHostInstance().showSaveDialog?.({ - title: 'FlipperExport', - defaultPath: path.join( - getRenderHostInstance().serverConfig.paths.homePath, - 'FlipperExport.flipper', - ), - }); - if (!file) { - return; - } const plugins = await selectPlugins(); if (plugins === false) { - return; // cancelled + return; } // TODO: no need to put this in the store, - // need to be cleaned up later in combination with SupportForm + // need to be cleaned up later in combination with SupportForm. dispatch(selectedPlugins(plugins)); Dialog.showModal((onHide) => ( - + )); } diff --git a/desktop/flipper-ui-core/src/utils/runHealthchecks.tsx b/desktop/flipper-ui-core/src/utils/runHealthchecks.tsx index 81c2f463969..7385d733133 100644 --- a/desktop/flipper-ui-core/src/utils/runHealthchecks.tsx +++ b/desktop/flipper-ui-core/src/utils/runHealthchecks.tsx @@ -58,7 +58,7 @@ async function launchHealthchecks(options: HealthcheckOptions): Promise { h.key, ) .catch((e) => { - console.error('Failed to run doctor check', e); + console.warn('Failed to run doctor check', e); return { status: 'FAILED', isAcknowledged: false, diff --git a/desktop/package.json b/desktop/package.json index 7364b0e6359..5180f759dca 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -67,10 +67,10 @@ "category": "facebook-intern", "description": "Mobile development tool", "devDependencies": { - "@babel/eslint-parser": "^7.19.1", + "@babel/eslint-parser": "^7.22.10", "@jest-runner/electron": "^3.0.1", "@testing-library/react": "^12.1.4", - "@types/jest": "^29.5.1", + "@types/jest": "^29.5.3", "@typescript-eslint/eslint-plugin": "^5.22.0", "@typescript-eslint/parser": "^5.55.0", "babel-eslint": "^10.1.0", @@ -169,7 +169,7 @@ "npm": "use yarn instead", "yarn": "^1.16" }, - "version": "0.210.1", + "version": "0.212.0", "workspaces": { "packages": [ "scripts", diff --git a/desktop/patches/@emotion+cache+11.5.0.patch b/desktop/patches/@emotion+cache+11.7.1.patch similarity index 91% rename from desktop/patches/@emotion+cache+11.5.0.patch rename to desktop/patches/@emotion+cache+11.7.1.patch index c77129dd9bf..1d28e46b234 100644 --- a/desktop/patches/@emotion+cache+11.5.0.patch +++ b/desktop/patches/@emotion+cache+11.7.1.patch @@ -1,8 +1,8 @@ diff --git a/node_modules/@emotion/cache/dist/emotion-cache.cjs.dev.js b/node_modules/@emotion/cache/dist/emotion-cache.cjs.dev.js -index 9a906b4..57f9d9d 100644 +index af9ac5a..195c3ff 100644 --- a/node_modules/@emotion/cache/dist/emotion-cache.cjs.dev.js +++ b/node_modules/@emotion/cache/dist/emotion-cache.cjs.dev.js -@@ -158,9 +158,10 @@ var createUnsafeSelectorsAlarm = function createUnsafeSelectorsAlarm(cache) { +@@ -159,9 +159,10 @@ var createUnsafeSelectorsAlarm = function createUnsafeSelectorsAlarm(cache) { return; } @@ -17,10 +17,10 @@ index 9a906b4..57f9d9d 100644 }; }; diff --git a/node_modules/@emotion/cache/dist/emotion-cache.esm.js b/node_modules/@emotion/cache/dist/emotion-cache.esm.js -index 5e5fa89..781c69a 100644 +index fd65cd3..40899c2 100644 --- a/node_modules/@emotion/cache/dist/emotion-cache.esm.js +++ b/node_modules/@emotion/cache/dist/emotion-cache.esm.js -@@ -149,9 +149,10 @@ var createUnsafeSelectorsAlarm = function createUnsafeSelectorsAlarm(cache) { +@@ -150,9 +150,10 @@ var createUnsafeSelectorsAlarm = function createUnsafeSelectorsAlarm(cache) { return; } diff --git a/desktop/patches/metro+0.69.0.patch b/desktop/patches/metro+0.70.2.patch similarity index 100% rename from desktop/patches/metro+0.69.0.patch rename to desktop/patches/metro+0.70.2.patch diff --git a/desktop/pkg-lib/package.json b/desktop/pkg-lib/package.json index 89e6fc33fed..12e03e910f0 100644 --- a/desktop/pkg-lib/package.json +++ b/desktop/pkg-lib/package.json @@ -11,10 +11,10 @@ "dependencies": { "chalk": "^4", "esbuild": "^0.15.7", - "fb-watchman": "^2.0.1", + "fb-watchman": "^2.0.2", "flipper-common": "0.0.0", "flipper-plugin-lib": "0.0.0", - "fs-extra": "^11.1.0", + "fs-extra": "^11.1.1", "metro": "^0.70.2", "metro-cache": "^0.70.2", "metro-minify-terser": "^0.75.0", diff --git a/desktop/pkg/package.json b/desktop/pkg/package.json index 5017d7e0ed7..588598dffd3 100644 --- a/desktop/pkg/package.json +++ b/desktop/pkg/package.json @@ -12,20 +12,20 @@ }, "bugs": "https://github.com/facebook/flipper/issues", "dependencies": { - "@oclif/command": "^1", - "@oclif/config": "^1", - "@oclif/parser": "^3.8.5", - "@oclif/plugin-help": "^5.1.12", - "@oclif/plugin-warn-if-update-available": "^2.0.14", + "@oclif/command": "^1.8.35", + "@oclif/config": "^1.18.16", + "@oclif/parser": "^3.8.16", + "@oclif/plugin-help": "^5.2.17", + "@oclif/plugin-warn-if-update-available": "^2.0.48", "ajv": "^6.12.2", "ajv-errors": "^1.0.1", "cli-ux": "^6.0.9", "flipper-pkg-lib": "0.0.0", "flipper-plugin-lib": "0.0.0", - "fs-extra": "^11.1.0", + "fs-extra": "^11.1.1", "inquirer": "^8.2.4", "lodash": "^4.17.21", - "recursive-readdir": "^2.2.2" + "recursive-readdir": "^2.2.3" }, "devDependencies": { "@oclif/dev-cli": "^1", diff --git a/desktop/plugin-lib/package.json b/desktop/plugin-lib/package.json index 80cd1d91f67..c57cc6f1a34 100644 --- a/desktop/plugin-lib/package.json +++ b/desktop/plugin-lib/package.json @@ -14,12 +14,12 @@ "decompress-targz": "^4.1.1", "decompress-unzip": "^4.0.1", "flipper-common": "^0.0.0", - "fs-extra": "^11.1.0", + "fs-extra": "^11.1.1", "live-plugin-manager": "^0.17.1", "npm-api": "^1.0.1", "p-filter": "^2.1.0", "p-map": "^4.0.0", - "semver": "^7.3.7", + "semver": "^7.5.4", "tmp": "^0.2.1" }, "devDependencies": { diff --git a/desktop/plugin-lib/src/pluginInstaller.tsx b/desktop/plugin-lib/src/pluginInstaller.tsx index eaa0bf16f06..365a44d6d86 100644 --- a/desktop/plugin-lib/src/pluginInstaller.tsx +++ b/desktop/plugin-lib/src/pluginInstaller.tsx @@ -108,8 +108,8 @@ export async function installPluginFromNpm(name: string) { } } -export async function installPluginFromFile( - packagePath: string, +export async function installPluginFromFileOrBuffer( + packagePath: string | Buffer, ): Promise { const tmpDir = await promisify(tmp.dir)(); try { diff --git a/desktop/plugins/public/layout/docs/setup.mdx b/desktop/plugins/public/layout/docs/setup.mdx index 2abb3ced710..0d7441e99f9 100644 --- a/desktop/plugins/public/layout/docs/setup.mdx +++ b/desktop/plugins/public/layout/docs/setup.mdx @@ -27,7 +27,7 @@ You also need to compile in the `litho-annotations` package, as Flipper reflects ```groovy dependencies { - debugImplementation 'com.facebook.flipper:flipper-litho-plugin:0.210.1' + debugImplementation 'com.facebook.flipper:flipper-litho-plugin:0.212.0' debugImplementation 'com.facebook.litho:litho-annotations:0.19.0' // ... } diff --git a/desktop/plugins/public/leak_canary/docs/setup.mdx b/desktop/plugins/public/leak_canary/docs/setup.mdx index 63f574f00ea..1b943ff357d 100644 --- a/desktop/plugins/public/leak_canary/docs/setup.mdx +++ b/desktop/plugins/public/leak_canary/docs/setup.mdx @@ -8,7 +8,7 @@ To setup the LeakCan ```groovy dependencies { - debugImplementation 'com.facebook.flipper:flipper-leakcanary2-plugin:0.210.1' + debugImplementation 'com.facebook.flipper:flipper-leakcanary2-plugin:0.212.0' debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1' } ``` diff --git a/desktop/plugins/public/network/docs/setup.mdx b/desktop/plugins/public/network/docs/setup.mdx index bdb911a909c..4a964b8f427 100644 --- a/desktop/plugins/public/network/docs/setup.mdx +++ b/desktop/plugins/public/network/docs/setup.mdx @@ -12,7 +12,7 @@ The network plugin is shipped as a separate Maven artifact, as follows: ```groovy dependencies { - debugImplementation 'com.facebook.flipper:flipper-network-plugin:0.210.1' + debugImplementation 'com.facebook.flipper:flipper-network-plugin:0.212.0' } ``` diff --git a/desktop/plugins/public/network/request-mocking/NetworkRouteManager.tsx b/desktop/plugins/public/network/request-mocking/NetworkRouteManager.tsx index 24f0a2bd694..9322d0bc840 100644 --- a/desktop/plugins/public/network/request-mocking/NetworkRouteManager.tsx +++ b/desktop/plugins/public/network/request-mocking/NetworkRouteManager.tsx @@ -139,6 +139,9 @@ export function createNetworkManager( }) .then((res) => { if (res) { + if (res.encoding !== 'utf-8' || typeof res.data !== 'string') { + return; + } const importedRoutes = JSON.parse(res.data); importedRoutes?.forEach((importedRoute: Route) => { if (importedRoute != null) { diff --git a/desktop/plugins/public/reactdevtools/package.json b/desktop/plugins/public/reactdevtools/package.json index 937a72523fb..32139443acb 100644 --- a/desktop/plugins/public/reactdevtools/package.json +++ b/desktop/plugins/public/reactdevtools/package.json @@ -31,8 +31,14 @@ "bugs": { "url": "https://github.com/facebook/flipper/issues" }, - "devDependencies": {}, + "devDependencies": { + "fs-extra": "^11.1.1", + "ts-node": "^10.9.1" + }, "peerDependencies": { "flipper-plugin": "*" + }, + "scripts": { + "postinstall": "ts-node scripts/remove-sourcemap-reference.tsx || true" } } diff --git a/desktop/plugins/public/reactdevtools/scripts/remove-sourcemap-reference.tsx b/desktop/plugins/public/reactdevtools/scripts/remove-sourcemap-reference.tsx new file mode 100644 index 00000000000..0901d07ce73 --- /dev/null +++ b/desktop/plugins/public/reactdevtools/scripts/remove-sourcemap-reference.tsx @@ -0,0 +1,62 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +/* eslint-disable no-restricted-imports */ + +/* + * This script attempts to get rid of a sourcemap reference in react-devtools-frontend + * that is causing a rather annoying non-fetal error at Flipper startup. + * + * It will gracefully fail as Flipper will still work without it, just show the error again. + */ + +import fs from 'fs-extra'; +import path from 'path'; + +const SOURCEMAP_REFERENCE = + '//# sourceMappingURL=importFile.worker.worker.js.map'; + +// Remove this once we're upgrade to a newer JS version. String.prototype.replaceAll is a thing. +function replaceAll(s: string, find: string, replace: string): string { + return s.replace( + new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), + replace, + ); +} + +async function main() { + const frontendPath = path.resolve( + __dirname, + '../../node_modules/react-devtools-inline/dist/frontend.js', + ); + console.log(`Looking up ${frontendPath} for patching ...`); + // Check if path exists + if (!(await fs.pathExists(frontendPath))) { + console.warn('react-devtools-inline frontend not found, skipping patching'); + return 0; + } + + const content = await fs.readFile(frontendPath, 'utf-8'); + if (!content.includes(SOURCEMAP_REFERENCE)) { + console.log('react-devtools-inline appears to already be patched.'); + return 0; + } + + await fs.writeFile( + frontendPath, + replaceAll(content, SOURCEMAP_REFERENCE, ''), + ); + + console.log('react-devtools-inline patched successfully.'); + return 0; +} + +(async () => { + process.exit(await main()); +})(); diff --git a/desktop/plugins/public/reactdevtools/scripts/tsconfig.json b/desktop/plugins/public/reactdevtools/scripts/tsconfig.json new file mode 100644 index 00000000000..7d5fb90c499 --- /dev/null +++ b/desktop/plugins/public/reactdevtools/scripts/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2017", + "module": "nodenext", + "jsx": "react", + "noEmit": true, + "strict": true, + "moduleResolution": "node", + "esModuleInterop": true + } +} + diff --git a/desktop/plugins/public/shared_preferences/src/index.tsx b/desktop/plugins/public/shared_preferences/src/index.tsx index 4e898569dff..a60dbd2b546 100644 --- a/desktop/plugins/public/shared_preferences/src/index.tsx +++ b/desktop/plugins/public/shared_preferences/src/index.tsx @@ -123,27 +123,31 @@ export function plugin(client: PluginClient) { } async function loadFromFile() { const file = await getFlipperLib().importFile(); - if (file?.path != undefined) { - const data = await getFlipperLib().remoteServerContext.fs.readFile( - file.path, - {encoding: 'utf-8'}, - ); - const preferences = JSON.parse(data) as SharedPreferencesEntry; - const name = selectedPreferences.get(); - if (name != null) { - updateSharedPreferences({ - name: name, - preferences: preferences.preferences, - }); - - for (const key in preferences.preferences) { - await client.send('setSharedPreference', { - sharedPreferencesName: name, - preferenceName: key, - preferenceValue: preferences.preferences[key], + if (file && file.encoding === 'utf-8' && typeof file.data === 'string') { + try { + const preferences = JSON.parse(file.data) as SharedPreferencesEntry; + const name = selectedPreferences.get(); + if (name != null) { + updateSharedPreferences({ + name: name, + preferences: preferences.preferences, }); + + for (const key in preferences.preferences) { + await client.send('setSharedPreference', { + sharedPreferencesName: name, + preferenceName: key, + preferenceValue: preferences.preferences[key], + }); + } } + } catch (e) { + console.warn('Unable to import shared preferences', e); } + } else { + console.warn( + 'The loaded file either has wrong encoding or is not a valid json file', + ); } } diff --git a/desktop/plugins/public/ui-debugger/ClientTypes.tsx b/desktop/plugins/public/ui-debugger/ClientTypes.tsx index 9090c6d23e1..a135b35264a 100644 --- a/desktop/plugins/public/ui-debugger/ClientTypes.tsx +++ b/desktop/plugins/public/ui-debugger/ClientTypes.tsx @@ -35,6 +35,7 @@ export type SubtreeUpdateEvent = { frameworkEvents?: FrameworkEvent[]; }; +export type NodeMap = Map; export type FrameworkEventType = string; export type FrameworkEventMetadata = { @@ -55,12 +56,14 @@ type FrameworkEventAttribution = Stacktrace | Reason | UpstreamEvent; export type FrameworkEvent = { id: number; + treeId?: Id; //todo should be mandatory once ios implements this nodeId: Id; type: FrameworkEventType; timestamp: number; - payload?: JSON; + payload?: JsonObject; + duration?: number; attribution?: FrameworkEventAttribution; - thread?: 'main' | string; + thread?: 'main' | string; //todo should be mandatory once ios implements this }; export type InitEvent = { @@ -183,7 +186,8 @@ export type Tag = | 'CK' | 'iOS' | 'BloksBoundTree' - | 'BloksDerived'; + | 'BloksDerived' + | 'TreeRoot'; export type Inspectable = | InspectableObject diff --git a/desktop/plugins/public/ui-debugger/DesktopTypes.tsx b/desktop/plugins/public/ui-debugger/DesktopTypes.tsx index d29d3344af1..b23c0afcc3e 100644 --- a/desktop/plugins/public/ui-debugger/DesktopTypes.tsx +++ b/desktop/plugins/public/ui-debugger/DesktopTypes.tsx @@ -11,6 +11,7 @@ import {Atom, _ReadOnlyAtom} from 'flipper-plugin'; import { Id, FrameworkEventType, + FrameworkEvent, Inspectable, Bounds, Tag, @@ -66,13 +67,18 @@ export type NestedNode = { export type ViewMode = | {mode: 'default'} - | {mode: 'frameworkEventsTable'; treeRootId: Id}; + | {mode: 'frameworkEventsTable'; nodeId: Id; isTree: boolean}; export type NodeSelection = { id: Id; source: SelectionSource; }; +export type AugmentedFrameworkEvent = FrameworkEvent & { + nodeName?: string; + rootComponentName?: string; +}; + export type OnSelectNode = ( node: Id | undefined, source: SelectionSource, diff --git a/desktop/plugins/public/ui-debugger/components/FrameworkEventsTable.tsx b/desktop/plugins/public/ui-debugger/components/FrameworkEventsTable.tsx index 746cbd60662..01466dd5851 100644 --- a/desktop/plugins/public/ui-debugger/components/FrameworkEventsTable.tsx +++ b/desktop/plugins/public/ui-debugger/components/FrameworkEventsTable.tsx @@ -7,65 +7,170 @@ * @format */ -import {PartitionOutlined} from '@ant-design/icons'; +import {DeleteOutlined, PartitionOutlined} from '@ant-design/icons'; import { DataTable, DataTableColumn, DataTableManager, + DetailSidebar, Layout, usePlugin, + useValue, } from 'flipper-plugin'; -import React, {useEffect, useRef} from 'react'; -import {FrameworkEvent, Id} from '../ClientTypes'; +import React, {useCallback, useEffect, useMemo, useRef} from 'react'; +import {FrameworkEvent, Id, NodeMap} from '../ClientTypes'; import {plugin} from '../index'; -import {Button, Tooltip} from 'antd'; +import {Button, Result, Tooltip} from 'antd'; +import {AugmentedFrameworkEvent} from '../DesktopTypes'; +import {formatDuration, formatTimestampMillis} from '../utils/timeUtils'; +import {eventTypeToName} from './sidebar/inspector/FrameworkEventsInspector'; +import {startCase} from 'lodash'; +import {Visualization2D} from './visualizer/Visualization2D'; +import {getNode} from '../utils/map'; +import {tracker} from '../utils/tracker'; -export function FrameworkEventsTable({rootTreeId}: {rootTreeId?: Id}) { +export function FrameworkEventsTable({ + nodeId, + isTree, + nodes, +}: { + nodeId: Id; + nodes: NodeMap; + isTree: boolean; +}) { const instance = usePlugin(plugin); - const managerRef = useRef | null>(null); + const focusedNode = useValue(instance.uiState.focusedNode); + const managerRef = useRef | null>( + null, + ); useEffect(() => { - if (rootTreeId != null) { + tracker.track('framework-event-table-opened', {}); + instance.uiActions.onSelectNode(undefined, 'tree'); + if (nodeId != null) { managerRef.current?.resetFilters(); - managerRef.current?.addColumnFilter('nodeId', rootTreeId as string); + if (isTree) { + managerRef.current?.addColumnFilter('treeId', nodeId as string, { + exact: true, + }); + } else { + managerRef.current?.addColumnFilter('nodeId', nodeId as string, { + exact: true, + }); + } } - }, [rootTreeId]); + }, [instance.uiActions, isTree, nodeId]); + + const allColumns = useMemo(() => { + const customColumnKeys = instance.frameworkEventsCustomColumns.get(); + + const customColumns = [...customColumnKeys].map( + (customKey: string) => + ({ + key: customKey, + title: startCase(customKey), + onRender: (row: AugmentedFrameworkEvent) => row.payload?.[customKey], + } as DataTableColumn), + ); + + return staticColumns.concat(customColumns); + }, [instance.frameworkEventsCustomColumns]); + + const onSelectRow = useCallback( + (event: FrameworkEvent | undefined): void => { + if (event != null) { + tracker.track('framework-event-table-row-selected', { + eventType: event.type, + }); + } + instance.uiActions.onFocusNode(event?.nodeId); + }, + [instance.uiActions], + ); return ( + enableAutoScroll dataSource={instance.frameworkEvents} tableManagerRef={managerRef} - columns={columns} + onSelect={onSelectRow} + columns={allColumns} extraActions={ - - - + <> + + + + + + + } /> + + {getNode(focusedNode, nodes) != null ? ( + + ) : ( + + )} + ); } -const columns: DataTableColumn[] = [ +const staticColumns: DataTableColumn[] = [ { key: 'timestamp', - onRender: (row: FrameworkEvent) => { - return new Date(row.timestamp).toLocaleTimeString(); - }, + onRender: (row: FrameworkEvent) => formatTimestampMillis(row.timestamp), + title: 'Timestamp', + }, + { + key: 'type', + title: 'Event type', + onRender: (row: FrameworkEvent) => eventTypeToName(row.type), + }, + { + key: 'duration', + title: 'Duration', + onRender: (row: FrameworkEvent) => + row.duration != null ? formatDuration(row.duration) : null, + }, + { + key: 'treeId', + title: 'TreeId', + }, + { + key: 'rootComponentName', + title: 'Root component name', }, { key: 'nodeId', + title: 'Component ID', }, { - key: 'type', + key: 'nodeName', + title: 'Component name', }, { key: 'thread', + title: 'Thread', + onRender: (row: FrameworkEvent) => startCase(row.thread), }, ]; diff --git a/desktop/plugins/public/ui-debugger/components/main.tsx b/desktop/plugins/public/ui-debugger/components/main.tsx index 82728bc8480..3f281ead7d1 100644 --- a/desktop/plugins/public/ui-debugger/components/main.tsx +++ b/desktop/plugins/public/ui-debugger/components/main.tsx @@ -23,7 +23,7 @@ import {PerfStats} from './PerfStats'; import {Visualization2D} from './visualizer/Visualization2D'; import {Inspector} from './sidebar/Inspector'; import {TreeControls} from './tree/TreeControls'; -import {Button, Spin} from 'antd'; +import {Button, Spin, Typography} from 'antd'; import {QueryClientProvider} from 'react-query'; import {Tree2} from './tree/Tree'; import {StreamInterceptorErrorView} from './StreamInterceptorErrorView'; @@ -43,16 +43,18 @@ export function Component() { useHotkeys('ctrl+i', () => setShowPerfStats((show) => !show)); const viewMode = useValue(instance.uiState.viewMode); - const [bottomPanelComponent, setBottomPanelComponent] = useState< - ReactNode | undefined + const [bottomPanel, setBottomPanel] = useState< + {title: string; component: ReactNode} | undefined >(); - const openBottomPanelWithContent = (component: ReactNode) => { - setBottomPanelComponent(component); + const openBottomPanelWithContent = (title: string, component: ReactNode) => { + setBottomPanel({title, component}); }; const dismissBottomPanel = () => { - setBottomPanelComponent(undefined); + setBottomPanel(undefined); }; + const [bottomPanelHeight, setBottomPanelHeight] = useState(400); + if (showPerfStats) return ( ; + return ( + + ); } return ( - - + - - - + + + + - { - instance.uiActions.setVisualiserWidth(width); - }} - gutter> - - - - - - - {bottomPanelComponent} - - + { + instance.uiActions.setVisualiserWidth(width); + }} + gutter> + + + + + + + {bottomPanel && ( + + {bottomPanel.component} + + )} + ); } @@ -164,10 +186,19 @@ export function Centered(props: {children: React.ReactNode}) { } type BottomPanelProps = { + title: string; dismiss: () => void; children: React.ReactNode; + height: number; + setHeight: (height: number) => void; }; -export function BottomPanel({dismiss, children}: BottomPanelProps) { +export function BottomPanel({ + title, + dismiss, + children, + height, + setHeight, +}: BottomPanelProps) { const bottomPanelRef = useRef(null); useEffect(() => { @@ -176,7 +207,10 @@ export function BottomPanel({dismiss, children}: BottomPanelProps) { bottomPanelRef.current && !bottomPanelRef.current.contains(event.target) ) { - dismiss(); + setTimeout(() => { + //push to back of event queue so that you can still select item in the tree + dismiss(); + }, 0); } }; // Add event listener when the component is mounted. @@ -191,15 +225,31 @@ export function BottomPanel({dismiss, children}: BottomPanelProps) { if (!children) { return <>; } + return (
- - {children} -
- -
+ setHeight(height)} + gutter> + + + {title} + + + + {children} + +
); diff --git a/desktop/plugins/public/ui-debugger/components/shared/FrameworkEventsTreeSelect.tsx b/desktop/plugins/public/ui-debugger/components/shared/FrameworkEventsTreeSelect.tsx new file mode 100644 index 00000000000..c598a5c146e --- /dev/null +++ b/desktop/plugins/public/ui-debugger/components/shared/FrameworkEventsTreeSelect.tsx @@ -0,0 +1,163 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import React, {ReactNode} from 'react'; +import {InfoCircleOutlined} from '@ant-design/icons'; +import {Tooltip, TreeSelect} from 'antd'; +import {Layout, theme} from 'flipper-plugin'; +import {FrameworkEventMetadata, FrameworkEventType} from '../../ClientTypes'; + +export function FrameworkEventsTreeSelect({ + treeData, + onSetEventSelected, + selected, + placeholder, + width, +}: { + width?: number; + placeholder: string; + selected: string[]; + treeData: TreeSelectNode[]; + onSetEventSelected: ( + eventType: FrameworkEventType, + selected: boolean, + ) => void; +}) { + return ( + { + for (const leaf of getAllLeaves(node)) { + onSetEventSelected(leaf, true); + } + }} + onDeselect={(_: any, node: any) => { + for (const leaf of getAllLeaves(node)) { + onSetEventSelected(leaf, false); + } + }} + /> + ); +} + +type TreeSelectNode = { + title: ReactNode; + titleValue: string; + key: string; + value: string; + children: TreeSelectNode[]; +}; + +/** + * In tree select you can select a parent which implicitly selects all children, we find them all here as the real state + * is in terms of the leaf nodes + */ +function getAllLeaves(treeSelectNode: TreeSelectNode) { + const result: string[] = []; + function getAllLeavesRec(node: TreeSelectNode) { + if (node.children.length > 0) { + for (const child of node.children) { + getAllLeavesRec(child); + } + } else { + result.push(node.key); + } + } + getAllLeavesRec(treeSelectNode); + return result; +} + +export const frameworkEventSeparator = '.'; +/** + * transformed flat event type data structure into tree + */ +export function buildTreeSelectData( + eventTypes: string[], + metadata: Map, +): TreeSelectNode[] { + const root: TreeSelectNode = buildTreeSelectNode('root', 'root', metadata); + + eventTypes.forEach((eventType) => { + const eventSubtypes = eventType.split(frameworkEventSeparator); + let currentNode = root; + + // Find the parent node for the current id + for (let i = 0; i < eventSubtypes.length - 1; i++) { + let foundChild = false; + for (const child of currentNode.children) { + if (child.titleValue === eventSubtypes[i]) { + currentNode = child; + foundChild = true; + break; + } + } + if (!foundChild) { + const newNode: TreeSelectNode = buildTreeSelectNode( + eventSubtypes[i], + eventSubtypes.slice(0, i + 1).join(frameworkEventSeparator), + metadata, + ); + + currentNode.children.push(newNode); + currentNode = newNode; + } + } + // Add the current id as a child of the parent node + currentNode.children.push( + buildTreeSelectNode( + eventSubtypes[eventSubtypes.length - 1], + eventSubtypes + .slice(0, eventSubtypes.length) + .join(frameworkEventSeparator), + metadata, + ), + ); + }); + + return root.children; +} + +function buildTreeSelectNode( + title: string, + fullValue: string, + metadata: Map, +): TreeSelectNode { + const documentation = metadata.get(fullValue)?.documentation; + return { + title: ( + + {title} + {documentation && ( + + + + )} + + ), + titleValue: title, + key: fullValue, + value: fullValue, + children: [], + }; +} diff --git a/desktop/plugins/public/ui-debugger/components/shared/MultiSelectableDropDownItem.tsx b/desktop/plugins/public/ui-debugger/components/shared/MultiSelectableDropDownItem.tsx new file mode 100644 index 00000000000..e499f89c4b2 --- /dev/null +++ b/desktop/plugins/public/ui-debugger/components/shared/MultiSelectableDropDownItem.tsx @@ -0,0 +1,51 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import React from 'react'; +import {Checkbox, Typography} from 'antd'; +import {Layout, styled, theme} from 'flipper-plugin'; + +export function MultiSelectableDropDownItem({ + value, + selectedValues, + onSelect, + text, +}: { + value: T; + selectedValues: Set; + onSelect: (value: T, selected: boolean) => void; + text: string; +}) { + const isSelected = selectedValues.has(value); + return ( + { + e.stopPropagation(); + onSelect(value, !isSelected); + }}> + { + onSelect(value, !isSelected); + }} + /> + {text} + + ); +} + +export const StyledMultiSelectDropDownItem = styled(Layout.Horizontal)({ + ':hover': { + backgroundColor: theme.backgroundWash, + }, + height: 32, +}); diff --git a/desktop/plugins/public/ui-debugger/components/shared/SelectableDropDownItem.tsx b/desktop/plugins/public/ui-debugger/components/shared/SelectableDropDownItem.tsx new file mode 100644 index 00000000000..e18e1255843 --- /dev/null +++ b/desktop/plugins/public/ui-debugger/components/shared/SelectableDropDownItem.tsx @@ -0,0 +1,37 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import {Menu} from 'antd'; +import {theme} from 'flipper-plugin'; +import React from 'react'; + +export function SelectableDropDownItem({ + value, + selectedValue, + onSelect, + text, +}: { + value: T; + selectedValue: T; + onSelect: (value: T) => void; + text: string; +}) { + return ( + { + onSelect(value); + }}> + {text} + + ); +} diff --git a/desktop/plugins/public/ui-debugger/components/sidebar/Inspector.tsx b/desktop/plugins/public/ui-debugger/components/sidebar/Inspector.tsx index cd8298206e8..0f5fe96f695 100644 --- a/desktop/plugins/public/ui-debugger/components/sidebar/Inspector.tsx +++ b/desktop/plugins/public/ui-debugger/components/sidebar/Inspector.tsx @@ -31,7 +31,7 @@ type Props = { os: DeviceOS; nodes: Map; metadata: Map; - showExtra: (element: ReactNode) => void; + showExtra: (title: string, element: ReactNode) => void; }; export const Inspector: React.FC = ({ @@ -43,6 +43,7 @@ export const Inspector: React.FC = ({ const instance = usePlugin(plugin); const selectedNodeId = useValue(instance.uiState.selectedNode)?.id; + const frameworkEventMetadata = useValue(instance.frameworkEventMetadata); const selectedNode = selectedNodeId ? nodes.get(selectedNodeId) : undefined; if (!selectedNode) { return ; @@ -122,6 +123,8 @@ export const Inspector: React.FC = ({ }> void; + showExtra?: (title: string, element: ReactNode) => void; + frameworkEventMetadata: Map; + onSetViewMode: (viewMode: ViewMode) => void; }; + export const FrameworkEventsInspector: React.FC = ({ node, events, showExtra, + frameworkEventMetadata, + onSetViewMode, }) => { - const [selectedEvent, setSelectedEvent] = useState( - events[events.length - 1], + const allThreads = uniqBy(events, 'thread').map((event) => event.thread); + const [filteredThreads, setFilteredThreads] = useState>( + new Set(), + ); + + const allEventTypes = uniqBy(events, 'type').map((event) => event.type); + const [filteredEventTypes, setFilteredEventTypes] = useState>( + new Set(), ); - const showStacktrace = () => { - const attribution = selectedEvent.attribution; - if (attribution?.type === 'stacktrace') { - const stacktraceInspector = ( - - ); - showExtra?.(stacktraceInspector); - } - }; - - const hasStacktrace = (event: FrameworkEvent) => { - return event?.attribution?.type === 'stacktrace'; - }; + const filteredEvents = events + .filter( + (event) => + filteredEventTypes.size === 0 || filteredEventTypes.has(event.type), + ) + .filter( + (event) => + filteredThreads.size === 0 || filteredThreads.has(event.thread!), + ); + const showThreadsSection = allThreads.length > 1; + const showEventTypesSection = allEventTypes.length > 1; return ( - <> + + + Event timeline + + + + - )} - + + ); +}; + +function EventDetails({ + event, + node, + frameworkEventMetadata, +}: { + frameworkEventMetadata?: FrameworkEventMetadata; + event: FrameworkEvent; + node: ClientNode; +}) { + const stackTrace = + event?.attribution?.type === 'stacktrace' ? ( + + ) : null; + + const details = ( + + + {event.type} + {frameworkEventMetadata && ( + + {frameworkEventMetadata?.documentation} + + )} + + + {event.thread} + + + {formatTimestampMillis(event.timestamp)} + + {event.duration && ( + + {formatDuration(event.duration)} + + )} + {event.payload && Object.keys(event.payload).length > 0 && ( + + + + )} + + + ); + + return ( + + {details} + {stackTrace} + ); +} + +export const options: Intl.DateTimeFormatOptions = { + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + hour12: false, }; + +export function eventTypeToName(eventType: string) { + return eventType.slice(eventType.lastIndexOf(frameworkEventSeparator) + 1); +} + +function threadToColor(thread?: string) { + return thread === 'main' ? theme.warningColor : theme.primaryColor; +} diff --git a/desktop/plugins/public/ui-debugger/components/tree/ContextMenu.tsx b/desktop/plugins/public/ui-debugger/components/tree/ContextMenu.tsx index ffd7bcfcf09..56044a33bd6 100644 --- a/desktop/plugins/public/ui-debugger/components/tree/ContextMenu.tsx +++ b/desktop/plugins/public/ui-debugger/components/tree/ContextMenu.tsx @@ -159,38 +159,44 @@ export const ContextMenu: React.FC<{ frameworkEvents.getAllRecordsByIndex({nodeId: hoveredNode.id})) ?? []; - const frameworkEventsTable = matchingFrameworkEvents.length > 0 && ( - { - onSetViewMode({ - mode: 'frameworkEventsTable', - treeRootId: hoveredNode?.id ?? '', - }); - }} - icon={} - /> - ); + const frameworkEventsTable = matchingFrameworkEvents.length > 0 && + hoveredNode && ( + { + onSetViewMode({ + mode: 'frameworkEventsTable', + nodeId: hoveredNode.id, + isTree: hoveredNode.tags.includes('TreeRoot'), + }); + }} + icon={} + /> + ); return ( { onContextMenuOpen(visible); }} - overlay={() => ( - - {treeCollapseItems} - {focus} - {removeFocus} - {frameworkEventsTable} - {(focus || removeFocus || frameworkEventsTable) && ( - - )} - {copyItems} + overlay={() => { + return ( + + {treeCollapseItems} + {focus} + {removeFocus} + {frameworkEventsTable} + {(focus || removeFocus || frameworkEventsTable) && ( + + )} + {copyItems} - {hoveredNode && } - - )} + {hoveredNode && ( + + )} + + ); + }} trigger={['contextMenu']}> {children} diff --git a/desktop/plugins/public/ui-debugger/components/tree/Tree.tsx b/desktop/plugins/public/ui-debugger/components/tree/Tree.tsx index 41260e20155..c67f5a5a914 100644 --- a/desktop/plugins/public/ui-debugger/components/tree/Tree.tsx +++ b/desktop/plugins/public/ui-debugger/components/tree/Tree.tsx @@ -55,7 +55,9 @@ export type TreeNode = ClientNode & { export function Tree2({ nodes, rootId, + additionalHeightOffset, }: { + additionalHeightOffset: number; nodes: Map; rootId: Id; }) { @@ -139,16 +141,22 @@ export function Tree2({ isUsingKBToScrollUtill, ); + const initialHeightOffset = useRef(null); useLayoutEffect(() => { //the grand parent gets its size correclty via flex box, we use its initial //position to size the scroll parent ref for react virtual, It uses vh which accounts for window size changes //However if we dynamically add content above or below we may need to revisit this approach const boundingClientRect = grandParentRef?.current?.getBoundingClientRect(); - parentRef.current!!.style.height = `calc(100vh - ${ - boundingClientRect!!.top - }px - ${window.innerHeight - boundingClientRect!!.bottom}px )`; - }, []); + if (initialHeightOffset.current == null) { + //it is important to capture the initial height offset as we dont want to consider them again if elements are added dynamically later + initialHeightOffset.current = + boundingClientRect!!.top + + (window.innerHeight - boundingClientRect!!.bottom) - + additionalHeightOffset; + } + parentRef.current!!.style.height = `calc(100vh - ${initialHeightOffset.current}px - ${additionalHeightOffset}px )`; + }, [additionalHeightOffset]); useLayoutEffect(() => { //scroll width is the width of the element including overflow, we grab the scroll width @@ -316,7 +324,7 @@ const IndentGuides = React.memo( width: indentGuideLinePadding, height: TreeItemHeight, borderRight: `1px solid`, - borderImage: `linear-gradient(to bottom, ${firstHalf} 50%, ${secondHalf} 50%) 1`, + borderImageSource: `linear-gradient(to bottom, ${firstHalf} 50%, ${secondHalf} 50%)`, borderImageSlice: 1, }} /> diff --git a/desktop/plugins/public/ui-debugger/components/tree/TreeControls.tsx b/desktop/plugins/public/ui-debugger/components/tree/TreeControls.tsx index a4213012a77..3e9003bef9f 100644 --- a/desktop/plugins/public/ui-debugger/components/tree/TreeControls.tsx +++ b/desktop/plugins/public/ui-debugger/components/tree/TreeControls.tsx @@ -15,9 +15,9 @@ import { Modal, Tooltip, Typography, - TreeSelect, Space, Switch, + Badge, } from 'antd'; import { EyeOutlined, @@ -26,7 +26,11 @@ import { SearchOutlined, } from '@ant-design/icons'; import {usePlugin, useValue, Layout} from 'flipper-plugin'; -import {FrameworkEventType} from '../../ClientTypes'; +import {FrameworkEventMetadata, FrameworkEventType} from '../../ClientTypes'; +import { + buildTreeSelectData, + FrameworkEventsTreeSelect, +} from '../shared/FrameworkEventsTreeSelect'; export const TreeControls: React.FC = () => { const instance = usePlugin(plugin); @@ -40,6 +44,8 @@ export const TreeControls: React.FC = () => { instance.uiState.frameworkEventMonitoring, ); + const frameworkEventMetadata = useValue(instance.frameworkEventMetadata); + const [showFrameworkEventsModal, setShowFrameworkEventsModal] = useState(false); @@ -65,18 +71,27 @@ export const TreeControls: React.FC = () => { }> {frameworkEventMonitoring.size > 0 && ( <> - + val === true, + ).length + }> + + ; visible: boolean; onCancel: () => void; onSetEventMonitored: ( @@ -118,6 +135,7 @@ function FrameworkEventsMonitoringModal({ const treeData = buildTreeSelectData( frameworkEventTypes.map(([type]) => type), + metadata, ); return ( @@ -133,28 +151,11 @@ function FrameworkEventsMonitoringModal({ of matching events in the tree - { - for (const leaf of getAllLeaves(node)) { - onSetEventMonitored(leaf, true); - } - }} - onDeselect={(_: any, node: any) => { - for (const leaf of getAllLeaves(node)) { - onSetEventMonitored(leaf, false); - } - }} /> @@ -172,80 +173,3 @@ function FrameworkEventsMonitoringModal({ ); } - -type TreeSelectNode = { - title: string; - key: string; - value: string; - children: TreeSelectNode[]; -}; - -/** - * In tree select you can select a parent which implicitly selects all children, we find them all here as the real state - * is in terms of the leaf nodes - */ -function getAllLeaves(treeSelectNode: TreeSelectNode) { - const result: string[] = []; - function getAllLeavesRec(node: TreeSelectNode) { - if (node.children.length > 0) { - for (const child of node.children) { - getAllLeavesRec(child); - } - } else { - result.push(node.key); - } - } - getAllLeavesRec(treeSelectNode); - return result; -} - -/** - * transformed flat event type data structure into tree - */ -function buildTreeSelectData(eventTypes: string[]): TreeSelectNode[] { - const root: TreeSelectNode = buildTreeSelectNode('root', 'root'); - - eventTypes.forEach((eventType) => { - const eventSubtypes = eventType.split(':'); - let currentNode = root; - - // Find the parent node for the current id - for (let i = 0; i < eventSubtypes.length - 1; i++) { - let foundChild = false; - for (const child of currentNode.children) { - if (child.title === eventSubtypes[i]) { - currentNode = child; - foundChild = true; - break; - } - } - if (!foundChild) { - const newNode: TreeSelectNode = buildTreeSelectNode( - eventSubtypes[i], - eventSubtypes.slice(0, i + 1).join(':'), - ); - - currentNode.children.push(newNode); - currentNode = newNode; - } - } - // Add the current id as a child of the parent node - currentNode.children.push( - buildTreeSelectNode( - eventSubtypes[eventSubtypes.length - 1], - eventSubtypes.slice(0, eventSubtypes.length).join(':'), - ), - ); - }); - - return root.children; -} - -function buildTreeSelectNode(title: string, fullValue: string): TreeSelectNode { - return { - title: title, - key: fullValue, - value: fullValue, - children: [], - }; -} diff --git a/desktop/plugins/public/ui-debugger/components/visualizer/Visualization2D.tsx b/desktop/plugins/public/ui-debugger/components/visualizer/Visualization2D.tsx index 7bd6b274ff1..a8afa87e406 100644 --- a/desktop/plugins/public/ui-debugger/components/visualizer/Visualization2D.tsx +++ b/desktop/plugins/public/ui-debugger/components/visualizer/Visualization2D.tsx @@ -31,8 +31,10 @@ export const Visualization2D: React.FC< width: number; nodes: Map; onSelectNode: OnSelectNode; + hideControls?: boolean; + disableInteractivity?: boolean; } & React.HTMLAttributes -> = ({width, nodes, onSelectNode}) => { +> = ({width, nodes, onSelectNode, hideControls, disableInteractivity}) => { const rootNodeRef = useRef(); const instance = usePlugin(plugin); @@ -62,6 +64,7 @@ export const Visualization2D: React.FC< const domRect = rootNodeRef.current?.getBoundingClientRect(); if ( + disableInteractivity || !focusState || !domRect || instance.uiState.isContextMenuOpen.get() || @@ -110,6 +113,7 @@ export const Visualization2D: React.FC< width, snapshotNode, instance.uiActions, + disableInteractivity, ]); useEffect(() => { @@ -146,14 +150,16 @@ export const Visualization2D: React.FC< return ( - + {!hideControls && ( + + )}
{ diff --git a/desktop/plugins/public/ui-debugger/components/visualizer/VisualizerControls.tsx b/desktop/plugins/public/ui-debugger/components/visualizer/VisualizerControls.tsx index ad9dcd9b4c6..9c7e558c874 100644 --- a/desktop/plugins/public/ui-debugger/components/visualizer/VisualizerControls.tsx +++ b/desktop/plugins/public/ui-debugger/components/visualizer/VisualizerControls.tsx @@ -21,6 +21,7 @@ import { import {tracker} from '../../utils/tracker'; import {debounce} from 'lodash'; import {WireFrameMode} from '../../DesktopTypes'; +import {SelectableDropDownItem} from '../shared/SelectableDropDownItem'; export type TargetModeState = | { state: 'selected'; @@ -182,31 +183,6 @@ export function VisualiserControls({ ); } -function SelectableDropDownItem({ - value, - selectedValue, - onSelect, - text, -}: { - value: T; - selectedValue: T; - onSelect: (value: T) => void; - text: string; -}) { - return ( - { - onSelect(value); - }}> - {text} - - ); -} - const debouncedReportTargetAdjusted = debounce(() => { tracker.track('target-mode-adjusted', {}); }, 500); diff --git a/desktop/plugins/public/ui-debugger/index.tsx b/desktop/plugins/public/ui-debugger/index.tsx index 6187ff09608..df336676977 100644 --- a/desktop/plugins/public/ui-debugger/index.tsx +++ b/desktop/plugins/public/ui-debugger/index.tsx @@ -11,7 +11,6 @@ import {createDataSource, createState, PluginClient} from 'flipper-plugin'; import { Events, FrameScanEvent, - FrameworkEvent, FrameworkEventType, Id, Metadata, @@ -19,6 +18,7 @@ import { PerformanceStatsEvent, SnapshotInfo, ClientNode, + FrameworkEventMetadata, } from './ClientTypes'; import { UIState, @@ -28,11 +28,14 @@ import { ReadOnlyUIState, LiveClientState, WireFrameMode, + AugmentedFrameworkEvent, } from './DesktopTypes'; import {getStreamInterceptor} from './fb-stubs/StreamInterceptor'; import {prefetchSourceFileLocation} from './components/fb-stubs/IDEContextMenu'; import {checkFocusedNodeStillActive} from './plugin/ClientDataUtils'; import {uiActions} from './plugin/uiActions'; +import {first} from 'lodash'; +import {getNode} from './utils/map'; type PendingData = { metadata: Record; @@ -45,10 +48,15 @@ export function plugin(client: PluginClient) { const streamInterceptor = getStreamInterceptor(client.device.os); const snapshot = createState(null); const nodesAtom = createState>(new Map()); - const frameworkEvents = createDataSource([], { + const frameworkEvents = createDataSource([], { indices: [['nodeId']], limit: 10000, }); + const frameworkEventsCustomColumns = createState>(new Set()); + + const frameworkEventMetadata = createState< + Map + >(new Map()); const uiState: UIState = createUIState(); @@ -78,6 +86,11 @@ export function plugin(client: PluginClient) { draft.set(frameworkEventMeta.type, false); }); }); + frameworkEventMetadata.update((draft) => { + event.frameworkEventMetadata?.forEach((frameworkEventMeta) => { + draft.set(frameworkEventMeta.type, frameworkEventMeta); + }); + }); }); client.onConnect(() => { @@ -197,10 +210,18 @@ export function plugin(client: PluginClient) { const processFrame = async (frameScan: FrameScanEvent) => { try { + const nodes = new Map( + frameScan.nodes.map((node) => [node.id, {...node}]), + ); + if (frameScan.frameTime > lastFrameTime) { + applyFrameData(nodes, frameScan.snapshot); + lastFrameTime = frameScan.frameTime; + } + applyFrameworkEvents(frameScan, nodes); + lastFrameTime = frameScan.frameTime; + const [processedNodes, additionalMetadata] = - await streamInterceptor.transformNodes( - new Map(frameScan.nodes.map((node) => [node.id, {...node}])), - ); + await streamInterceptor.transformNodes(nodes); metadata.update((draft) => { for (const metadata of additionalMetadata) { @@ -208,14 +229,10 @@ export function plugin(client: PluginClient) { } }); - if (frameScan.frameTime > lastFrameTime) { + if (frameScan.frameTime >= lastFrameTime) { applyFrameData(processedNodes, frameScan.snapshot); lastFrameTime = frameScan.frameTime; } - - applyFrameworkEvents(frameScan); - - return true; } catch (error) { pendingData.frame = frameScan; handleStreamError('Frame', error); @@ -223,10 +240,26 @@ export function plugin(client: PluginClient) { } }; - function applyFrameworkEvents(frameScan: FrameScanEvent) { + function applyFrameworkEvents( + frameScan: FrameScanEvent, + nodes: Map, + ) { + const customColumns = frameworkEventsCustomColumns.get(); for (const frameworkEvent of frameScan.frameworkEvents ?? []) { - frameworkEvents.append(frameworkEvent); + for (const key in frameworkEvent.payload) { + customColumns.add(key); + } + + const treeRoot = getNode(frameworkEvent.treeId, nodes); + + const treeRootFirstChild = getNode(first(treeRoot?.children), nodes); + frameworkEvents.append({ + ...frameworkEvent, + nodeName: nodes.get(frameworkEvent.nodeId)?.name, + rootComponentName: treeRootFirstChild?.name, + }); } + frameworkEventsCustomColumns.set(customColumns); if (uiState.isPaused.get() === true) { return; @@ -301,6 +334,8 @@ export function plugin(client: PluginClient) { uiActions: uiActions(uiState, nodesAtom, snapshot, mutableLiveClientData), nodes: nodesAtom, frameworkEvents, + frameworkEventMetadata, + frameworkEventsCustomColumns, snapshot, metadata, perfEvents, diff --git a/desktop/plugins/public/ui-debugger/utils/map.tsx b/desktop/plugins/public/ui-debugger/utils/map.tsx index 5c839f96b67..2f66d5b9c43 100644 --- a/desktop/plugins/public/ui-debugger/utils/map.tsx +++ b/desktop/plugins/public/ui-debugger/utils/map.tsx @@ -9,7 +9,10 @@ import {ClientNode, Id} from '../ClientTypes'; -export function getNode(id: Id | undefined, nodes: Map) { +export function getNode( + id: Id | undefined, + nodes: Map, +): ClientNode | undefined { //map just returns undefined when you pass null or undefined as a key return nodes.get(id!); } diff --git a/desktop/plugins/public/ui-debugger/utils/timeUtils.tsx b/desktop/plugins/public/ui-debugger/utils/timeUtils.tsx new file mode 100644 index 00000000000..b2c6a47f1fc --- /dev/null +++ b/desktop/plugins/public/ui-debugger/utils/timeUtils.tsx @@ -0,0 +1,33 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import {options} from '../components/sidebar/inspector/FrameworkEventsInspector'; + +export function formatTimestampMillis(timestamp: number): string { + const date = new Date(timestamp); + + const formattedDate = new Intl.DateTimeFormat('en-US', options).format(date); + const milliseconds = date.getMilliseconds(); + + return `${formattedDate}.${milliseconds.toString().padStart(3, '0')}`; +} + +export function formatDuration(nanoseconds: number): string { + if (nanoseconds < 1_000) { + return `${nanoseconds} nanoseconds`; + } else if (nanoseconds < 1_000_000) { + return `${(nanoseconds / 1_000).toFixed(2)} microseconds`; + } else if (nanoseconds < 1_000_000_000) { + return `${(nanoseconds / 1_000_000).toFixed(2)} milliseconds`; + } else if (nanoseconds < 1_000_000_000_000) { + return `${(nanoseconds / 1_000_000_000).toFixed(2)} seconds`; + } else { + return `${(nanoseconds / (1_000_000_000 * 60)).toFixed(2)} minutes`; + } +} diff --git a/desktop/plugins/public/ui-debugger/utils/tracker.tsx b/desktop/plugins/public/ui-debugger/utils/tracker.tsx index 4b9d67e0b42..b0aa1850ae8 100644 --- a/desktop/plugins/public/ui-debugger/utils/tracker.tsx +++ b/desktop/plugins/public/ui-debugger/utils/tracker.tsx @@ -30,6 +30,14 @@ type TrackerEvents = { eventType: FrameworkEventType; monitored: boolean; }; + 'framework-event-table-row-selected': { + eventType: FrameworkEventType; + }; + 'framework-event-table-opened': {}; + 'framework-event-timeline-filters-adjusted': {}; + 'framework-event-timeline-event-selected': { + eventType: FrameworkEventType; + }; 'search-term-updated': { searchTerm: string; }; diff --git a/desktop/plugins/public/yarn.lock b/desktop/plugins/public/yarn.lock index 5f0e4ee8470..286120e3b8b 100644 --- a/desktop/plugins/public/yarn.lock +++ b/desktop/plugins/public/yarn.lock @@ -52,6 +52,13 @@ dependencies: regenerator-runtime "^0.13.11" +"@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" + "@icons/material@^0.2.4": version "0.2.4" resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" @@ -68,6 +75,24 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@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" + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -189,6 +214,26 @@ "@babel/runtime" "^7.12.5" "@testing-library/dom" "^7.28.1" +"@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.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + "@types/aria-query@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" @@ -354,6 +399,16 @@ JSONSelect@0.2.1: resolved "https://registry.yarnpkg.com/JSONSelect/-/JSONSelect-0.2.1.tgz#415418a526d33fe31d74b4defa3c836d485ec203" integrity sha1-QVQYpSbTP+MddLTe+jyDbUhewgM= +acorn-walk@^8.1.1: + 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== + +acorn@^8.4.1: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + ansi-regex@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" @@ -373,6 +428,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + aria-query@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" @@ -626,6 +686,11 @@ core-js-pure@^3.0.0: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -879,6 +944,11 @@ detect-node@^2.0.4, detect-node@^2.1.0: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dom-accessibility-api@^0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.4.tgz#b06d059cdd4a4ad9a79275f9d414a5c126241166" @@ -1001,6 +1071,15 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +fs-extra@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" + integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" @@ -1085,6 +1164,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== +graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -1363,6 +1447,15 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -1448,6 +1541,11 @@ magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -2227,6 +2325,25 @@ traverse@0.4.x: resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.4.6.tgz#d04b2280e4c792a5815429ef7b8b60c64c9ccc34" integrity sha1-0EsigOTHkqWBVCnve4tgxkyczDQ= +ts-node@^10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + 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" + yn "3.1.1" + ts-retry-promise@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/ts-retry-promise/-/ts-retry-promise-0.7.0.tgz#08f2dcbbf5d2981495841cb63389a268324e8147" @@ -2252,6 +2369,11 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + unload@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7" @@ -2278,6 +2400,11 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== +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== + which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -2306,3 +2433,8 @@ xml-beautifier@^0.4.0: integrity sha512-jtqVgG2mXX+mZYSq80tPWBcrtPGL3JwCtcME52c7Aau1R34quuJw86R9A+KFO7F6EQAaagUmMXGhDRKGV3UXhw== dependencies: repeat-string "1.6.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== diff --git a/desktop/scripts/build-flipper-server-release.tsx b/desktop/scripts/build-flipper-server-release.tsx index 897083f0b80..09530343f8b 100644 --- a/desktop/scripts/build-flipper-server-release.tsx +++ b/desktop/scripts/build-flipper-server-release.tsx @@ -90,11 +90,6 @@ const argv = yargs type: 'boolean', default: false, }, - tcp: { - describe: 'Enable TCP connections on flipper-server.', - type: 'boolean', - default: true, - }, 'rebuild-plugins': { describe: 'Enables rebuilding of default plugins on Flipper build. Only make sense in conjunction with "--no-bundled-plugins". Enabled by default, but if disabled using "--no-plugin-rebuild", then plugins are just released as is without rebuilding. This can save some time if you know plugin bundles are already up-to-date.', @@ -356,29 +351,17 @@ async function runPostBuildAction(archive: string, dir: string) { // didn't change console.log(`⚙️ Installing flipper-server.tgz using npx`); await fs.remove(path.join(homedir(), '.npm', '_npx')); - await spawn( - 'npx', - [ - archive, - argv.open ? '--open' : '--no-open', - argv.tcp ? '--tcp' : '--no-tcp', - ], - { - stdio: 'inherit', - shell: true, - }, - ); + await spawn('npx', [archive, argv.open ? '--open' : '--no-open'], { + stdio: 'inherit', + shell: true, + }); } else if (argv.start) { console.log(`⚙️ Starting flipper-server from build dir`); - await spawn( - './server.js', - [argv.open ? '--open' : '--no-open', argv.tcp ? '--tcp' : '--no-tcp'], - { - cwd: dir, - stdio: 'inherit', - shell: true, - }, - ); + await spawn('./server.js', [argv.open ? '--open' : '--no-open'], { + cwd: dir, + stdio: 'inherit', + shell: true, + }); } } diff --git a/desktop/scripts/build-release.tsx b/desktop/scripts/build-release.tsx index bccc2b16d0c..99047dc04bb 100755 --- a/desktop/scripts/build-release.tsx +++ b/desktop/scripts/build-release.tsx @@ -205,9 +205,13 @@ async function buildDist(buildFolder: string) { if (argv['mac-dmg']) { targetsRaw.push(Platform.MAC.createTarget(['dmg'])); } + const macPath = path.join( + distDir, + process.arch === 'arm64' ? 'mac-arm64' : 'mac', + ); postBuildCallbacks.push(() => spawn('zip', ['-qyr9', '../Flipper-mac.zip', 'Flipper.app'], { - cwd: path.join(distDir, 'mac'), + cwd: macPath, encoding: 'utf-8', }), ); diff --git a/desktop/scripts/build-utils.tsx b/desktop/scripts/build-utils.tsx index 44975e0cf80..314e3cc5e71 100644 --- a/desktop/scripts/build-utils.tsx +++ b/desktop/scripts/build-utils.tsx @@ -384,11 +384,7 @@ export function sleep(ms: number) { let proc: child.ChildProcess | undefined; -export async function launchServer( - startBundler: boolean, - open: boolean, - tcp: boolean, -) { +export async function launchServer(startBundler: boolean, open: boolean) { if (proc) { console.log('⚙️ Killing old flipper-server...'); proc.kill(9); @@ -401,7 +397,6 @@ export async function launchServer( `../flipper-server/server.js`, startBundler ? `--bundler` : `--no-bundler`, open ? `--open` : `--no-open`, - tcp ? `--tcp` : `--no-tcp`, ], { cwd: serverDir, diff --git a/desktop/scripts/jest-setup-after.tsx b/desktop/scripts/jest-setup-after.tsx index f2cc9e65086..57a3066e761 100644 --- a/desktop/scripts/jest-setup-after.tsx +++ b/desktop/scripts/jest-setup-after.tsx @@ -22,6 +22,7 @@ import { ReleaseChannel, Tristate, parseEnvironmentVariables, + uuid, } from 'flipper-common'; // Only import the type! @@ -131,6 +132,7 @@ Object.defineProperty(global, 'matchMedia', { function createStubRenderHost(): RenderHost { const rootPath = resolve(__dirname, '..'); const stubConfig: FlipperServerConfig = { + sessionId: uuid(), environmentInfo: { processId: process.pid, appVersion: '0.0.0', diff --git a/desktop/scripts/package.json b/desktop/scripts/package.json index 47f178a84b6..2a5aedf99d1 100644 --- a/desktop/scripts/package.json +++ b/desktop/scripts/package.json @@ -8,10 +8,10 @@ "bugs": "https://github.com/facebook/flipper/issues", "devDependencies": { "@adobe/node-fetch-retry": "^2.2.0", - "@babel/code-frame": "^7.18.6", + "@babel/code-frame": "^7.22.10", "@types/adobe__node-fetch-retry": "^1.0.4", "@types/babel__code-frame": "^7.0.3", - "@types/detect-port": "^1.3.2", + "@types/detect-port": "^1.3.3", "@types/fs-extra": "^9.0.13", "@types/node": "^17.0.31", "ansi-to-html": "^0.7.2", diff --git a/desktop/scripts/start-flipper-server-dev.tsx b/desktop/scripts/start-flipper-server-dev.tsx index fd407495d9c..aae4740e560 100644 --- a/desktop/scripts/start-flipper-server-dev.tsx +++ b/desktop/scripts/start-flipper-server-dev.tsx @@ -44,11 +44,6 @@ const argv = yargs '[FB-internal only] Will force using public sources only, to be able to iterate quickly on the public version. If sources are checked out from GitHub this is already the default. Setting env var "FLIPPER_FORCE_PUBLIC_BUILD" is equivalent.', type: 'boolean', }, - tcp: { - describe: 'Enable TCP connections on flipper-server.', - type: 'boolean', - default: true, - }, channel: { description: 'Release channel for the build', choices: ['stable', 'insiders'], @@ -108,7 +103,7 @@ async function copyStaticResources() { async function restartServer() { try { await compileServerMain(true); - await launchServer(true, ++startCount === 1, argv.tcp); // only open on the first time + await launchServer(true, ++startCount === 1); // only open on the first time } catch (e) { console.error( chalk.red( diff --git a/desktop/static/CHANGELOG.md b/desktop/static/CHANGELOG.md index 75857723c80..0831f9a9342 100644 --- a/desktop/static/CHANGELOG.md +++ b/desktop/static/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.212.0 (18/8/2023) + + * [D48280921](https://github.com/facebook/flipper/search?q=D48280921&type=Commits) - [internal] internal + + # 0.210.0 (2/8/2023) * [D47832249](https://github.com/facebook/flipper/search?q=D47832249&type=Commits) - [UIDebugger] Fixed bug with keyboard tree controls diff --git a/desktop/static/index.web.dev.html b/desktop/static/index.web.dev.html index 64f8808e539..b90fee0e48b 100644 --- a/desktop/static/index.web.dev.html +++ b/desktop/static/index.web.dev.html @@ -21,7 +21,7 @@ } +
+
+ Flipper is not running in the background + +

It can be started by clicking the button below.

+
+ +
+
+

+ Flipper will automatically reload once the connection is re-established. +

+

If is taking a bit longer than it should, you can manually start Flipper.

+

From the terminal, please run:

+ +
+
+

shell

+
+
+

> open -a 'Flipper' --args '--server'

+
+
+
+
+
-
+
Connecting...
@@ -56,6 +136,39 @@ let suppressErrors = false; let connected = false; + // Listen to changes in the network state, reload when online. + // This handles the case when the device is completely offline + // i.e. no network connection. + window.addEventListener('online', () => { + window.location.reload(); + }); + + // Check if the server is responding & reload the page if it is. + // This handles the case when the device is online, but the server + // is offline or misbehaving. + async function checkNetworkAndReload() { + try { + const response = await fetch('.'); + if (response.status >= 200 && response.status < 500) { + window.location.reload(); + return; + } + } catch { + // Unable to connect to the server, ignore. + } + window.setTimeout(checkNetworkAndReload, 2500); + } + + function showNoConnection() { + const root = document.getElementById('root'); + root.remove(); + + const troubleshoot = document.getElementById('troubleshoot'); + troubleshoot.style.display = 'flex'; + + checkNetworkAndReload(); + } + const params = new URL(location.href).searchParams; let token = params.get('token'); if (!token) { @@ -73,7 +186,7 @@ if (typeof message.event === 'string') { switch (message.event) { case 'hasErrors': { - openError(message.payload); + showMessage(message.payload); suppressErrors = true; break; } @@ -90,10 +203,10 @@ socket.addEventListener('error', (e) => { if (!connected) { - openError('Socket failed to connect. Is the server running? Have you provided a valid authentication token?'); + showMessage('Socket failed to connect. Is the server running? Have you provided a valid authentication token?'); } else { - openError('Socket failed with error.'); + showMessage('Socket failed with error.'); } suppressErrors = true; @@ -103,7 +216,7 @@ connected = true; }) - function openError(text) { + function showMessage(text) { if (suppressErrors) { return; } @@ -113,7 +226,8 @@ box.textContent = text; } } - window.flipperShowError = openError; + window.flipperShowMessage = showMessage; + window.flipperShowNoConnection = showNoConnection; // load correct theme (n.b. this doesn't handle system value specifically, will assume light in such cases) try { @@ -132,31 +246,12 @@ script.src = window.flipperConfig.entryPoint; script.onerror = (e) => { - openError('Failed to load entry point. Check Chrome console for more info.'); + showMessage('Failed to load entry point. Check Chrome console for more info.'); }; document.body.appendChild(script); } - if ('serviceWorker' in navigator) { - navigator.serviceWorker - .register('/service-worker.js') - .then(() => { - console.log('Flipper Service Worker has been registered'); - }) - .catch((e) => { - console.error('Flipper failed to register Service Worker', e); - }); - } - - window.addEventListener('beforeinstallprompt', (e) => { - console.log('Flipper PWA before install prompt with event', e); - // Prevent Chrome 67 and earlier from automatically showing the prompt. - e.preventDefault(); - // Stash the event so it can be triggered later. - global.PWAppInstallationEvent = e; - }); - init(); })(); diff --git a/desktop/static/index.web.html b/desktop/static/index.web.html index 9095cb6d128..5aa5ed20bf3 100644 --- a/desktop/static/index.web.html +++ b/desktop/static/index.web.html @@ -21,7 +21,7 @@ } diff --git a/desktop/static/package.json b/desktop/static/package.json index e68c89825d1..35794958a5b 100644 --- a/desktop/static/package.json +++ b/desktop/static/package.json @@ -9,9 +9,9 @@ "fix-path": "^3.0.0", "mkdirp": "^1.0.4", "node-fetch": "^2.6.7", - "ws": "^8.6.0", + "ws": "^8.13.0", "xdg-basedir": "^4.0.0", - "yargs": "^17.6.2" + "yargs": "^17.7.2" }, "devDependencies": { "@types/mkdirp": "^1.0.2" diff --git a/desktop/static/service-worker.js b/desktop/static/service-worker.js index 31bc03a72ed..12cb7ce1df5 100644 --- a/desktop/static/service-worker.js +++ b/desktop/static/service-worker.js @@ -52,8 +52,7 @@ self.addEventListener('fetch', (event) => { } // Always try the network first (try flipper server) - const networkResponse = await fetch(event.request); - return networkResponse; + return await fetch(event.request); } catch (error) { // Catch is only triggered if an exception is thrown, which is likely // due to a network error. @@ -62,8 +61,7 @@ self.addEventListener('fetch', (event) => { console.log('Fetch failed; returning offline page instead.', error); const cache = await caches.open(CACHE_NAME); - const cachedResponse = await cache.match(OFFLINE_URL); - return cachedResponse; + return await cache.match(OFFLINE_URL); } })()); } diff --git a/desktop/yarn.lock b/desktop/yarn.lock index b7c4604a41c..f41c7367b3a 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -201,6 +201,14 @@ dependencies: "@babel/highlight" "^7.18.6" +"@babel/code-frame@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.10.tgz#1c20e612b768fefa75f6e90d6ecb86329247f0a3" + integrity sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA== + dependencies: + "@babel/highlight" "^7.22.10" + chalk "^2.4.2" + "@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60" @@ -305,14 +313,14 @@ json5 "^2.2.2" semver "^6.3.0" -"@babel/eslint-parser@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz#4f68f6b0825489e00a24b41b6a1ae35414ecd2f4" - integrity sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ== +"@babel/eslint-parser@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.22.10.tgz#bfdf3d1b32ad573fe7c1c3447e0b485e3a41fd09" + integrity sha512-0J8DNPRXQRLeR9rPaUMM3fA+RbixjnVLe/MRMYCkp3hzgsSuxCHQ8NN8xQG1wIHKJ4a1DTROTvFJdW+B5/eOsg== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" eslint-visitor-keys "^2.1.0" - semver "^6.3.0" + semver "^6.3.1" "@babel/generator@^7.14.0", "@babel/generator@^7.17.3", "@babel/generator@^7.18.0", "@babel/generator@^7.20.14", "@babel/generator@^7.20.7": version "7.20.14" @@ -911,6 +919,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== +"@babel/helper-validator-identifier@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" + integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== + "@babel/helper-validator-option@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" @@ -1009,6 +1022,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.10.tgz#02a3f6d8c1cb4521b2fd0ab0da8f4739936137d7" + integrity sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ== + dependencies: + "@babel/helper-validator-identifier" "^7.22.5" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@babel/parser@^7.1.0", "@babel/parser@^7.14.0", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.7.0": version "7.17.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0" @@ -3513,7 +3535,7 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@oclif/command@^1", "@oclif/command@^1.8.14", "@oclif/command@^1.8.15": +"@oclif/command@^1.8.14", "@oclif/command@^1.8.15": version "1.8.16" resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.8.16.tgz#bea46f81b2061b47e1cda318a0b923e62ca4cc0c" integrity sha512-rmVKYEsKzurfRU0xJz+iHelbi1LGlihIWZ7Qvmb/CBz1EkhL7nOkW4SVXmG2dA5Ce0si2gr88i6q4eBOMRNJ1w== @@ -3525,6 +3547,18 @@ debug "^4.1.1" semver "^7.3.2" +"@oclif/command@^1.8.35": + version "1.8.35" + resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.8.35.tgz#7023f48a6b058d33ccb578c28a1522fba192efd2" + integrity sha512-oILFTe3n6WjEbhXaSJd6FPsU4H97WxkC3Q0+Y63pfTXIZ424Fb9Hlg1CazscWcJqCrhuuUag6mItdgYo0kpinw== + dependencies: + "@oclif/config" "^1.18.2" + "@oclif/errors" "^1.3.6" + "@oclif/help" "^1.0.1" + "@oclif/parser" "^3.8.16" + debug "^4.1.1" + semver "^7.5.4" + "@oclif/config@1.18.2": version "1.18.2" resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.18.2.tgz#5bfe74a9ba6a8ca3dceb314a81bd9ce2e15ebbfe" @@ -3537,7 +3571,19 @@ is-wsl "^2.1.1" tslib "^2.0.0" -"@oclif/config@^1", "@oclif/config@^1.18.2": +"@oclif/config@^1.18.16": + version "1.18.16" + resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.18.16.tgz#3235d260ab1eb8388ebb6255bca3dd956249d796" + integrity sha512-VskIxVcN22qJzxRUq+raalq6Q3HUde7sokB7/xk5TqRZGEKRVbFeqdQBxDWwQeudiJEgcNiMvIFbMQ43dY37FA== + dependencies: + "@oclif/errors" "^1.3.6" + "@oclif/parser" "^3.8.16" + debug "^4.3.4" + globby "^11.1.0" + is-wsl "^2.1.1" + tslib "^2.6.1" + +"@oclif/config@^1.18.2": version "1.18.6" resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.18.6.tgz#37367026b3110a2f04875509b1920a8ee4489f21" integrity sha512-OWhCpdu4QqggOPX1YPZ4XVmLLRX+lhGjXV6RNA7sogOwLqlEmSslnN/lhR5dkhcWZbKWBQH29YCrB3LDPRu/IA== @@ -3549,7 +3595,7 @@ is-wsl "^2.1.1" tslib "^2.3.1" -"@oclif/core@^1.1.1", "@oclif/core@^1.20.4", "@oclif/core@^1.3.6": +"@oclif/core@^1.1.1": version "1.20.4" resolved "https://registry.yarnpkg.com/@oclif/core/-/core-1.20.4.tgz#7378b52e1f1b502e383ffb07f95dffc9fd8588ff" integrity sha512-giug32M4YhSYNYKQwE1L57/+k5gp1+Bq3/0vKNQmzAY1tizFGhvBJc6GIRZasHjU+xtZLutQvrVrJo7chX3hxg== @@ -3583,6 +3629,42 @@ widest-line "^3.1.0" wrap-ansi "^7.0.0" +"@oclif/core@^2.11.8": + version "2.11.8" + resolved "https://registry.yarnpkg.com/@oclif/core/-/core-2.11.8.tgz#780c4fdf53e8569cf754c2a8fefcc7ddeacf1747" + integrity sha512-GILmztcHBzze45GvxRpUvqQI5nM26kSE/Q21Y+6DtMR+C8etM/hFW26D3uqIAbGlGtg5QEZZ6pjA/Fqgz+gl3A== + dependencies: + "@types/cli-progress" "^3.11.0" + ansi-escapes "^4.3.2" + ansi-styles "^4.3.0" + cardinal "^2.1.1" + chalk "^4.1.2" + clean-stack "^3.0.1" + cli-progress "^3.12.0" + debug "^4.3.4" + ejs "^3.1.8" + fs-extra "^9.1.0" + get-package-type "^0.1.0" + globby "^11.1.0" + hyperlinker "^1.0.0" + indent-string "^4.0.0" + is-wsl "^2.2.0" + js-yaml "^3.14.1" + natural-orderby "^2.0.3" + object-treeify "^1.1.33" + password-prompt "^1.1.2" + semver "^7.5.3" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + supports-color "^8.1.1" + supports-hyperlinks "^2.2.0" + ts-node "^10.9.1" + tslib "^2.5.0" + widest-line "^3.1.0" + wordwrap "^1.0.0" + wrap-ansi "^7.0.0" + "@oclif/dev-cli@^1": version "1.26.10" resolved "https://registry.yarnpkg.com/@oclif/dev-cli/-/dev-cli-1.26.10.tgz#d8df3a79009b68552f5e7f249d1d19ca52278382" @@ -3644,7 +3726,7 @@ resolved "https://registry.yarnpkg.com/@oclif/linewrap/-/linewrap-1.0.0.tgz#aedcb64b479d4db7be24196384897b5000901d91" integrity sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw== -"@oclif/parser@^3.8.0", "@oclif/parser@^3.8.5", "@oclif/parser@^3.8.6", "@oclif/parser@^3.8.9": +"@oclif/parser@^3.8.0", "@oclif/parser@^3.8.6", "@oclif/parser@^3.8.9": version "3.8.9" resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.9.tgz#9399041ada7e465043f34b24f4d82a8beb68a023" integrity sha512-1j/kThdse7yHQz6+c3v8RA1I3gD6+SGt2O7IAb/MAMoxqyBrFQDabQHH2UU4eVFGMLN7U91AiYJp11zJ9LcQAg== @@ -3654,6 +3736,16 @@ chalk "^4.1.0" tslib "^2.4.1" +"@oclif/parser@^3.8.16": + version "3.8.16" + resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.16.tgz#bedfc55153075b8b2925657f8865035aa877515c" + integrity sha512-jeleXSh5izmBQ6vwyCJmbFPahPpd/ajxASi25FaYAWcvwVMzP/vKAKQXKWZun6T9K/gd6ywSsTpfAXiZAjBd6g== + dependencies: + "@oclif/errors" "^1.3.6" + "@oclif/linewrap" "^1.0.0" + chalk "^4.1.0" + tslib "^2.6.1" + "@oclif/plugin-help@3.2.18": version "3.2.18" resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-3.2.18.tgz#f2bf6ba86719c174fc0e4c2149f73b46006bfdbd" @@ -3671,25 +3763,25 @@ widest-line "^3.1.0" wrap-ansi "^6.2.0" -"@oclif/plugin-help@^5.1.12": - version "5.1.12" - resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-5.1.12.tgz#24a18631eb9b22cb55e1a3b8e4f6039fd42727e6" - integrity sha512-HvH/RubJxqCinP0vUWQLTOboT+SfjfL8h40s+PymkWaldIcXlpoRaJX50vz+SjZIs7uewZwEk8fzLqpF/BWXlg== +"@oclif/plugin-help@^5.2.17": + version "5.2.17" + resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-5.2.17.tgz#72c549b1db8e16060ee4f320db96291ca341430f" + integrity sha512-8dhvATZZnkD8uq3etsvbVjjpdxiTqXTPjkMlU8ToQz09DL5BBzYApm65iTHFE0Vn9DPbKcNxX1d8YiF3ilgMOQ== dependencies: - "@oclif/core" "^1.3.6" + "@oclif/core" "^2.11.8" -"@oclif/plugin-warn-if-update-available@^2.0.14": - version "2.0.14" - resolved "https://registry.yarnpkg.com/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-2.0.14.tgz#f9142095f13c5e8300705533165ae039daa0c5f8" - integrity sha512-gEgFZuNtFx3yPfSuxhAm9F8nLZ4+UnBJhbjTywY0Cvrqvd+OvKvo6PfwRm0lWmH4EgWwQEq39pfaks1fg+y1gw== +"@oclif/plugin-warn-if-update-available@^2.0.48": + version "2.0.48" + resolved "https://registry.yarnpkg.com/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-2.0.48.tgz#0abdacbcded0bb060c207c403fdd6c31b486a81a" + integrity sha512-ISq3l8qFM6DYT2EkwBlYSyD3kKP2BqZ/nKhd3IBwYY6QJ17XwZ/bqne47oEzU1mvKEcRRU4B4AL4DN2quVqHrA== dependencies: - "@oclif/core" "^1.20.4" + "@oclif/core" "^2.11.8" chalk "^4.1.0" debug "^4.1.0" fs-extra "^9.0.1" http-call "^5.2.2" lodash "^4.17.21" - semver "^7.3.8" + semver "^7.5.4" "@oclif/screen@^1.0.4", "@oclif/screen@^1.0.4 ": version "1.0.4" @@ -3897,6 +3989,13 @@ "@types/connect" "*" "@types/node" "*" +"@types/cli-progress@^3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@types/cli-progress/-/cli-progress-3.11.0.tgz#ec79df99b26757c3d1c7170af8422e0fc95eef7e" + integrity sha512-XhXhBv1R/q2ahF3BM7qT5HLzJNlIL0wbcGyZVjqOTqAybAnsLisd7gy1UCyIqpL+5Iv6XhlSyzjLCnI2sIdbCg== + dependencies: + "@types/node" "*" + "@types/component-emitter@^1.2.10": version "1.2.11" resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506" @@ -3938,10 +4037,10 @@ resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.1.tgz#71cfabb247c22bcc16d536111f50c0ed12476b03" integrity sha512-mMUu4nWHLBlHtxXY17Fg6+ucS/MnndyOWyOe7MmwkoMYxvfQU2ajtRaEvqSUv+aVkMqH/C0NCI8UoVfRNQ10yg== -"@types/detect-port@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/detect-port/-/detect-port-1.3.2.tgz#8c06a975e472803b931ee73740aeebd0a2eb27ae" - integrity sha512-xxgAGA2SAU4111QefXPSp5eGbDm/hW6zhvYl9IeEPZEry9F4d66QAHm5qpUXjb6IsevZV/7emAEx5MhP6O192g== +"@types/detect-port@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@types/detect-port/-/detect-port-1.3.3.tgz#124c5d4c283f48a21f80826bcf39433b3e64aa81" + integrity sha512-bV/jQlAJ/nPY3XqSatkGpu+nGzou+uSwrH1cROhn+jBFg47yaNH+blW4C7p9KhopC7QxCv/6M86s37k8dMk0Yg== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": version "4.17.19" @@ -4063,10 +4162,10 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^29.5.1": - version "29.5.1" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.1.tgz#83c818aa9a87da27d6da85d3378e5a34d2f31a47" - integrity sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ== +"@types/jest@^29.5.3": + version "29.5.3" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.3.tgz#7a35dc0044ffb8b56325c6802a4781a626b05777" + integrity sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA== dependencies: expect "^29.0.0" pretty-format "^29.0.0" @@ -6114,6 +6213,13 @@ cli-progress@^3.10.0: dependencies: string-width "^4.2.0" +cli-progress@^3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/cli-progress/-/cli-progress-3.12.0.tgz#807ee14b66bcc086258e444ad0f19e7d42577942" + integrity sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A== + dependencies: + string-width "^4.2.3" + cli-progress@^3.4.0: version "3.6.0" resolved "https://registry.yarnpkg.com/cli-progress/-/cli-progress-3.6.0.tgz#20317e6a653c3e5636fb5f03a7d67cd48ebc215a" @@ -6780,15 +6886,15 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== -deep-equal@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.1.tgz#c72ab22f3a7d3503a4ca87dde976fe9978816739" - integrity sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ== +deep-equal@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.2.tgz#9b2635da569a13ba8e1cc159c2f744071b115daa" + integrity sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA== dependencies: array-buffer-byte-length "^1.0.0" call-bind "^1.0.2" es-get-iterator "^1.1.3" - get-intrinsic "^1.2.0" + get-intrinsic "^1.2.1" is-arguments "^1.1.1" is-array-buffer "^3.0.2" is-date-object "^1.0.5" @@ -7072,6 +7178,13 @@ ejs@^3.1.6, ejs@^3.1.7: dependencies: jake "^10.8.5" +ejs@^3.1.8: + version "3.1.9" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.9.tgz#03c9e8777fe12686a9effcef22303ca3d8eeb361" + integrity sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ== + dependencies: + jake "^10.8.5" + electron-builder@23.0.3: version "23.0.3" resolved "https://registry.yarnpkg.com/electron-builder/-/electron-builder-23.0.3.tgz#16264a0d8e3d40da1467bcc8ef7917538b54a3bc" @@ -8080,13 +8193,20 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -fb-watchman@^2.0.0, fb-watchman@^2.0.1: +fb-watchman@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== dependencies: bser "2.1.1" +fb-watchman@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + fbjs-css-vars@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" @@ -8359,6 +8479,15 @@ fs-extra@^11.1.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs-extra@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" + integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" @@ -8443,7 +8572,7 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== @@ -8779,10 +8908,10 @@ hosted-git-info@^4.0.2, hosted-git-info@^4.1.0: dependencies: lru-cache "^6.0.0" -hotkeys-js@^3.9.3: - version "3.9.3" - resolved "https://registry.yarnpkg.com/hotkeys-js/-/hotkeys-js-3.9.3.tgz#4b755cc695b388d7f93a83aff4b0c2a45719996c" - integrity sha512-s+f0xyvDmf6+DyrFQ2SY+eA7lbvMbjqkqi0I0SpMgnN5tZx7DeH8nsWhkJR4KEq3pxDPHJppDUhdt1rZFW5LeQ== +hotkeys-js@^3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/hotkeys-js/-/hotkeys-js-3.12.0.tgz#5534a7ffdba923df489ffbd876b991979beb2c77" + integrity sha512-Z+N573ycUKIGwFYS3ID1RzMJiGmtWMGKMiaNLyJS8B1ei+MllF4ZYmKS2T0kMWBktOz+WZLVNikftEgnukOrXg== html-encoding-sniffer@^3.0.0: version "3.0.0" @@ -11399,7 +11528,7 @@ minimatch@3.0.4: dependencies: brace-expansion "^1.1.7" -minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.2: +minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -13032,15 +13161,15 @@ react-virtual@^2.10.4: dependencies: "@reach/observe-rect" "^1.1.0" -react-virtualized-auto-sizer@^1.0.7: +react-virtualized-auto-sizer@1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.7.tgz#bfb8414698ad1597912473de3e2e5f82180c1195" integrity sha512-Mxi6lwOmjwIjC1X4gABXMJcKHsOo0xWl3E3ugOgufB8GJU+MqrtY35aBuvCYv/razQ1Vbp7h1gWJjGjoNN5pmA== -react-window@^1.8.6: - version "1.8.6" - resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.6.tgz#d011950ac643a994118632665aad0c6382e2a112" - integrity sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg== +react-window@^1.8.9: + version "1.8.9" + resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.9.tgz#24bc346be73d0468cdf91998aac94e32bc7fa6a8" + integrity sha512-+Eqx/fj1Aa5WnhRfj9dJg4VYATGwIUP2ItwItiJ6zboKWA6EX3lYDAXfGF2hyNqplEprhbtjbipiADEcwQ823Q== dependencies: "@babel/runtime" "^7.0.0" memoize-one ">=3.1.1 <6" @@ -13138,12 +13267,12 @@ reconnecting-websocket@^4.4.0: resolved "https://registry.yarnpkg.com/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz#3b0e5b96ef119e78a03135865b8bb0af1b948783" integrity sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng== -recursive-readdir@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" - integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== +recursive-readdir@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz#e726f328c0d69153bcabd5c322d3195252379372" + integrity sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA== dependencies: - minimatch "3.0.4" + minimatch "^3.0.5" redeyed@~2.1.0: version "2.1.1" @@ -13164,13 +13293,20 @@ redux-persist@^6.0.0: resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8" integrity sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ== -redux@^4.0.0, redux@^4.0.5, redux@^4.1.2: +redux@^4.0.0, redux@^4.0.5: version "4.1.2" resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104" integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw== dependencies: "@babel/runtime" "^7.9.2" +redux@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" + integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== + dependencies: + "@babel/runtime" "^7.9.2" + regenerate-unicode-properties@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" @@ -13383,10 +13519,10 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= -reselect@^4.1.7: - version "4.1.7" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.7.tgz#56480d9ff3d3188970ee2b76527bd94a95567a42" - integrity sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A== +reselect@^4.1.8: + version "4.1.8" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" + integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== resize-observer-polyfill@^1.5.0, resize-observer-polyfill@^1.5.1: version "1.5.1" @@ -13741,6 +13877,18 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semve resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.3, semver@^7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + send@0.17.2: version "0.17.2" resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" @@ -14681,6 +14829,11 @@ tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== +tslib@^2.5.0, tslib@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410" + integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -15255,6 +15408,11 @@ word-wrap@^1.2.3, word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -15317,21 +15475,16 @@ write-json-file@^4.1.1: sort-keys "^4.0.0" write-file-atomic "^3.0.0" -ws@8.8.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.0.tgz#8e71c75e2f6348dbf8d78005107297056cb77769" - integrity sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ== +ws@8.13.0, ws@^8.11.0, ws@^8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== ws@^7.5.1: version "7.5.7" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== -ws@^8.11.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== - ws@^8.6.0: version "8.6.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.6.0.tgz#e5e9f1d9e7ff88083d0c0dd8281ea662a42c9c23" @@ -15478,7 +15631,7 @@ yargs@^17.0.1, yargs@^17.6.0: y18n "^5.0.5" yargs-parser "^21.0.0" -yargs@^17.3.1: +yargs@^17.3.1, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -15491,19 +15644,6 @@ yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.1.1" -yargs@^17.6.2: - version "17.6.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.2.tgz#2e23f2944e976339a1ee00f18c77fedee8332541" - integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - yauzl@^2.10.0, yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" diff --git a/docs/getting-started/android-native.mdx b/docs/getting-started/android-native.mdx index 97fcda2915b..2fe40cc2be6 100644 --- a/docs/getting-started/android-native.mdx +++ b/docs/getting-started/android-native.mdx @@ -24,10 +24,10 @@ repositories { } dependencies { - debugImplementation 'com.facebook.flipper:flipper:0.210.1' + debugImplementation 'com.facebook.flipper:flipper:0.212.0' debugImplementation 'com.facebook.soloader:soloader:0.10.5' - releaseImplementation 'com.facebook.flipper:flipper-noop:0.210.1' + releaseImplementation 'com.facebook.flipper:flipper-noop:0.212.0' } ``` @@ -124,10 +124,10 @@ repositories { } dependencies { - debugImplementation 'com.facebook.flipper:flipper:0.210.2-SNAPSHOT' + debugImplementation 'com.facebook.flipper:flipper:0.212.1-SNAPSHOT' debugImplementation 'com.facebook.soloader:soloader:0.10.5' - releaseImplementation 'com.facebook.flipper:flipper-noop:0.210.2-SNAPSHOT' + releaseImplementation 'com.facebook.flipper:flipper-noop:0.212.1-SNAPSHOT' } ``` diff --git a/docs/getting-started/ios-native.mdx b/docs/getting-started/ios-native.mdx index 12fc19a4442..4f662aaecc1 100644 --- a/docs/getting-started/ios-native.mdx +++ b/docs/getting-started/ios-native.mdx @@ -19,7 +19,7 @@ The following configuration assumes CocoaPods 1.9+: ```ruby project 'MyApp.xcodeproj' -flipperkit_version = '0.210.0' +flipperkit_version = '0.212.0' target 'MyApp' do platform :ios, '10.0' diff --git a/docs/getting-started/react-native-ios.mdx b/docs/getting-started/react-native-ios.mdx index 442b3a236e2..9fddba609c4 100644 --- a/docs/getting-started/react-native-ios.mdx +++ b/docs/getting-started/react-native-ios.mdx @@ -51,7 +51,7 @@ Add all of the code below to your `ios/Podfile`: platform :ios, '9.0' def flipper_pods() - flipperkit_version = '0.210.1' # should match the version of your Flipper client app + flipperkit_version = '0.212.0' # should match the version of your Flipper client app pod 'FlipperKit', '~>' + flipperkit_version, :configuration => 'Debug' pod 'FlipperKit/FlipperKitLayoutPlugin', '~>' + flipperkit_version, :configuration => 'Debug' pod 'FlipperKit/SKIOSNetworkPlugin', '~>' + flipperkit_version, :configuration => 'Debug' diff --git a/docs/getting-started/react-native.mdx b/docs/getting-started/react-native.mdx index 200e30c441a..8ce4021d3ba 100644 --- a/docs/getting-started/react-native.mdx +++ b/docs/getting-started/react-native.mdx @@ -34,7 +34,7 @@ Latest version of Flipper requires react-native 0.69+! If you use react-native < Android: -1. Bump the `FLIPPER_VERSION` variable in `android/gradle.properties`, for example: `FLIPPER_VERSION=0.210.1`. +1. Bump the `FLIPPER_VERSION` variable in `android/gradle.properties`, for example: `FLIPPER_VERSION=0.212.0`. 2. Run `./gradlew clean` in the `android` directory. iOS: @@ -44,7 +44,7 @@ react-native version => 0.69.0 2. Run `pod install --repo-update` in the `ios` directory. react-native version < 0.69.0 -1. Call `use_flipper` with a specific version in `ios/Podfile`, for example: `use_flipper!({ 'Flipper' => '0.210.1' })`. +1. Call `use_flipper` with a specific version in `ios/Podfile`, for example: `use_flipper!({ 'Flipper' => '0.212.0' })`. 2. Run `pod install --repo-update` in the `ios` directory. ## Manual Setup diff --git a/gradle.properties b/gradle.properties index 11ce7f4957d..cd9f6e6d9b3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. # POM publishing constants -VERSION_NAME=0.210.2-SNAPSHOT +VERSION_NAME=0.212.1-SNAPSHOT GROUP=com.facebook.flipper SONATYPE_STAGING_PROFILE=comfacebook POM_URL=https://github.com/facebook/flipper diff --git a/iOS/FlipperKit/FlipperWebSocket.mm b/iOS/FlipperKit/FlipperWebSocket.mm index 53529b88274..241f096e06a 100644 --- a/iOS/FlipperKit/FlipperWebSocket.mm +++ b/iOS/FlipperKit/FlipperWebSocket.mm @@ -121,6 +121,14 @@ if (socket_ == NULL) { return; } + + // Ensure the payload size is valid before sending. + // The maximum allowed size for a message payload is 2^53 - 1. But that is + // for the entire message, including any additional metadata. + if (message.length() > pow(2, 53) - 1) { + throw std::length_error("Payload is too big to send"); + } + NSString* messageObjc = [NSString stringWithUTF8String:message.c_str()]; [socket_ send:messageObjc withCompletionHandler:^(NSError*) { diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseExecuteSql.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseExecuteSql.h new file mode 100644 index 00000000000..d1b80c4e54d --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseExecuteSql.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#include + +@interface DatabaseExecuteSqlResponse : NSObject + +@property(nonatomic, strong) NSString* type; +@property(nonatomic, strong) NSArray* columns; +@property(nonatomic, strong) NSArray* values; +@property(nonatomic, strong) NSNumber* insertedId; +@property(nonatomic, assign) NSInteger affectedCount; + +- (instancetype)initWithType:(NSString*)type + columns:(NSArray*)columns + values:(NSArray*)values + insertedId:(NSNumber*)insertedId + affectedCount:(NSInteger)affectedCount; + +@end + +@interface DatabaseExecuteSqlRequest : NSObject + +@property(nonatomic, assign, readonly) NSInteger databaseId; +@property(nonatomic, copy, readonly) NSString* value; + +- (instancetype)initWithDatabaseId:(NSInteger)databaseId value:(NSString*)value; ++ (DatabaseExecuteSqlRequest*)getExecuteSqlRequestFromDictionary: + (NSDictionary*)dictionary; + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseExecuteSql.m b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseExecuteSql.m new file mode 100644 index 00000000000..a63981717a4 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseExecuteSql.m @@ -0,0 +1,54 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "DatabaseExecuteSql.h" +#include + +@implementation DatabaseExecuteSqlResponse + +- (instancetype)initWithType:(NSString*)type + columns:(NSArray*)columns + values:(NSArray*)values + insertedId:(NSNumber*)insertedId + affectedCount:(NSInteger)affectedCount { + self = [super init]; + if (self) { + _type = type; + _columns = [columns copy]; + _values = [values copy]; + _insertedId = insertedId; + _affectedCount = affectedCount; + } + return self; +} + +@end + +@implementation DatabaseExecuteSqlRequest + +- (instancetype)initWithDatabaseId:(NSInteger)databaseId + value:(NSString*)value { + self = [super init]; + if (self) { + _databaseId = databaseId; + _value = [value copy]; + } + return self; +} + ++ (DatabaseExecuteSqlRequest*)getExecuteSqlRequestFromDictionary: + (NSDictionary*)dictionary { + NSInteger databaseId = [dictionary[@"databaseId"] integerValue]; + NSString* value = dictionary[@"value"]; + if (databaseId <= 0 || value.length == 0) { + return nil; + } + return [[DatabaseExecuteSqlRequest alloc] initWithDatabaseId:databaseId + value:value]; +} + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableData.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableData.h new file mode 100644 index 00000000000..e8417befd53 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableData.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface DatabaseGetTableDataResponse : NSObject + +@property(nonatomic, strong, readonly) NSArray* columns; +@property(nonatomic, strong, readonly) NSArray* values; +@property(nonatomic, assign, readonly) NSInteger start; +@property(nonatomic, assign, readonly) NSInteger count; +@property(nonatomic, assign, readonly) NSInteger total; + +- (instancetype)initWithColumns:(NSArray*)columns + values:(NSArray*)values + start:(NSInteger)start + count:(NSInteger)count + total:(NSInteger)total; + +@end + +@interface DatabaseGetTableDataRequest : NSObject + +@property(nonatomic, assign, readonly) NSInteger databaseId; +@property(nonatomic, copy, readonly) NSString* table; +@property(nonatomic, copy, readonly) NSString* order; +@property(nonatomic, assign, readonly) BOOL reverse; +@property(nonatomic, assign, readonly) NSInteger start; +@property(nonatomic, assign, readonly) NSInteger count; + +- (instancetype)initWithDatabaseId:(NSInteger)databaseId + table:(NSString*)table + order:(NSString*)order + reverse:(BOOL)reverse + start:(NSInteger)start + count:(NSInteger)count; + ++ (DatabaseGetTableDataRequest*)getTableDataRequestFromDictionary: + (NSDictionary*)dictionary; + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableData.m b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableData.m new file mode 100644 index 00000000000..d5666614fd5 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableData.m @@ -0,0 +1,69 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "DatabaseGetTableData.h" + +@implementation DatabaseGetTableDataResponse + +- (instancetype)initWithColumns:(NSArray*)columns + values:(NSArray*)values + start:(NSInteger)start + count:(NSInteger)count + total:(NSInteger)total { + self = [super init]; + if (self) { + _columns = [columns copy]; + _values = [values copy]; + _start = start; + _count = count; + _total = total; + } + return self; +} + +@end + +@implementation DatabaseGetTableDataRequest + +- (instancetype)initWithDatabaseId:(NSInteger)databaseId + table:(NSString*)table + order:(NSString*)order + reverse:(BOOL)reverse + start:(NSInteger)start + count:(NSInteger)count { + self = [super init]; + if (self) { + _databaseId = databaseId; + _table = [table copy]; + _order = [order copy]; + _reverse = reverse; + _start = start; + _count = count; + } + return self; +} + ++ (DatabaseGetTableDataRequest*)getTableDataRequestFromDictionary: + (NSDictionary*)dictionary { + NSInteger databaseId = [dictionary[@"databaseId"] integerValue]; + NSString* table = dictionary[@"table"]; + NSString* order = dictionary[@"order"]; + BOOL reverse = [dictionary[@"reverse"] boolValue]; + NSInteger start = [dictionary[@"start"] integerValue]; + NSInteger count = [dictionary[@"count"] integerValue]; + if (databaseId <= 0 || table.length == 0) { + return nil; + } + return [[DatabaseGetTableDataRequest alloc] initWithDatabaseId:databaseId + table:table + order:order + reverse:reverse + start:start + count:count]; +} + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableInfo.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableInfo.h new file mode 100644 index 00000000000..9103c40be24 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableInfo.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface DatabaseGetTableInfoResponse : NSObject + +@property(nonatomic, strong) NSString* definition; + +- (instancetype)initWithDefinition:(NSString*)definition; + +@end + +@interface DatabaseGetTableInfoRequest : NSObject + +@property(nonatomic, assign, readonly) NSInteger databaseId; +@property(nonatomic, copy, readonly) NSString* table; + +- (instancetype)initWithDatabaseId:(NSInteger)databaseId table:(NSString*)table; ++ (DatabaseGetTableInfoRequest*)getTableInfoRequestFromDictionary: + (NSDictionary*)dictionary; + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableInfo.m b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableInfo.m new file mode 100644 index 00000000000..e7e7b962982 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableInfo.m @@ -0,0 +1,46 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "DatabaseGetTableInfo.h" + +@implementation DatabaseGetTableInfoResponse + +- (instancetype)initWithDefinition:(NSString*)definition { + self = [super init]; + if (self) { + _definition = definition; + } + return self; +} + +@end + +@implementation DatabaseGetTableInfoRequest + +- (instancetype)initWithDatabaseId:(NSInteger)databaseId + table:(NSString*)table { + self = [super init]; + if (self) { + _databaseId = databaseId; + _table = [table copy]; + } + return self; +} + ++ (DatabaseGetTableInfoRequest*)getTableInfoRequestFromDictionary: + (NSDictionary*)dictionary { + NSNumber* databaseId = @([dictionary[@"databaseId"] integerValue]); + NSString* table = dictionary[@"table"]; + if (databaseId == nil || table == nil) { + return nil; + } + return [[DatabaseGetTableInfoRequest alloc] + initWithDatabaseId:databaseId.intValue + table:table]; +} + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableStructure.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableStructure.h new file mode 100644 index 00000000000..82309b1c55a --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableStructure.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface DatabaseGetTableStructureResponse : NSObject + +@property(nonatomic, strong, readonly) NSArray* structureColumns; +@property(nonatomic, strong, readonly) + NSArray*>* structureValues; +@property(nonatomic, strong, readonly) NSArray* indexesColumns; +@property(nonatomic, strong, readonly) + NSArray*>* indexesValues; + +- (instancetype) + initWithStructureColumns:(NSArray*)structureColumns + structureValues:(NSArray*>*)structureValues + indexesColumns:(NSArray*)indexesColumns + indexesValues:(NSArray*>*)indexesValues; + +@end + +@interface DatabaseGetTableStructureRequest : NSObject + +@property(nonatomic, assign, readonly) NSInteger databaseId; +@property(nonatomic, copy, readonly) NSString* table; + +- (instancetype)initWithDatabaseId:(NSInteger)databaseId table:(NSString*)table; ++ (DatabaseGetTableStructureRequest*)getTableStructureRequestFromDictionary: + (NSDictionary*)dictionary; + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableStructure.m b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableStructure.m new file mode 100644 index 00000000000..715b616a0d5 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Commands/DatabaseGetTableStructure.m @@ -0,0 +1,52 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "DatabaseGetTableStructure.h" + +@implementation DatabaseGetTableStructureResponse + +- (instancetype) + initWithStructureColumns:(NSArray*)structureColumns + structureValues:(NSArray*>*)structureValues + indexesColumns:(NSArray*)indexesColumns + indexesValues:(NSArray*>*)indexesValues { + self = [super init]; + if (self) { + _structureColumns = [structureColumns copy]; + _structureValues = [structureValues copy]; + _indexesColumns = [indexesColumns copy]; + _indexesValues = [indexesValues copy]; + } + return self; +} + +@end + +@implementation DatabaseGetTableStructureRequest + +- (instancetype)initWithDatabaseId:(NSInteger)databaseId + table:(NSString*)table { + self = [super init]; + if (self) { + _databaseId = databaseId; + _table = [table copy]; + } + return self; +} + ++ (DatabaseGetTableStructureRequest*)getTableStructureRequestFromDictionary: + (NSDictionary*)params { + int databaseId = [params[@"databaseId"] integerValue]; + NSString* table = params[@"table"]; + if (databaseId <= 0 || !table) { + return nil; + } + return [[DatabaseGetTableStructureRequest alloc] initWithDatabaseId:databaseId + table:table]; +} + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDescriptor.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDescriptor.h new file mode 100644 index 00000000000..3132fdce0da --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDescriptor.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@protocol DatabaseDescriptor +- (NSString*)name; +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDescriptorHolder.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDescriptorHolder.h new file mode 100644 index 00000000000..109d3c98a7d --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDescriptorHolder.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import "DatabaseDescriptor.h" +#import "DatabaseDriver.h" + +@interface DatabaseDescriptorHolder : NSObject + +@property(nonatomic, assign, readonly) NSInteger identifier; +@property(nonatomic, strong, readonly) id databaseDriver; +@property(nonatomic, strong, readonly) id + databaseDescriptor; + +- (instancetype)initWithIdentifier:(NSInteger)identifier + databaseDriver:(id)databaseDriver + databaseDescriptor:(id)databaseDescriptor; + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDescriptorHolder.m b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDescriptorHolder.m new file mode 100644 index 00000000000..467f340ae96 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDescriptorHolder.m @@ -0,0 +1,24 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "DatabaseDescriptorHolder.h" + +@implementation DatabaseDescriptorHolder + +- (instancetype)initWithIdentifier:(NSInteger)identifier + databaseDriver:(id)databaseDriver + databaseDescriptor:(id)databaseDescriptor { + self = [super init]; + if (self) { + _identifier = identifier; + _databaseDriver = databaseDriver; + _databaseDescriptor = databaseDescriptor; + } + return self; +} + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDriver.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDriver.h new file mode 100644 index 00000000000..140ba33872a --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseDriver.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@protocol DatabaseDescriptor; +@class DatabaseGetTableStructureResponse; +@class DatabaseGetTableInfoResponse; +@class DatabaseGetTableDataResponse; +@class DatabaseExecuteSqlResponse; + +@protocol DatabaseDriver +- (NSArray>*)getDatabases; +- (NSArray*)getTableNames:(id)databaseDescriptor; +- (DatabaseGetTableStructureResponse*) + getTableStructureWithDatabaseDescriptor: + (id)databaseDescriptor + forTable:(NSString*)tableName; +- (DatabaseGetTableInfoResponse*) + getTableInfoWithDatabaseDescriptor: + (id)databaseDescriptor + forTable:(NSString*)tableName; + +- (DatabaseGetTableDataResponse*) + getTableDataWithDatabaseDescriptor: + (id)databaseDescriptor + forTable:(NSString*)tableName + order:(NSString*)order + reverse:(BOOL)reverse + start:(NSInteger)start + count:(NSInteger)count; +- (DatabaseExecuteSqlResponse*)executeSQL:(NSString*)sql; +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseErrorCodes.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseErrorCodes.h new file mode 100644 index 00000000000..e97a7e43175 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabaseErrorCodes.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +typedef NS_ENUM(NSInteger, DatabasesErrorCodes) { + DatabasesErrorCodesInvalidRequest = 1, + DatabasesErrorCodesDatabaseInvalid = 2, + DatabasesErrorCodesSqlExecutionException = 3, +}; + +static NSString* const kDatabasesErrorCodesInvalidRequestMessage = + @"The request received was invalid"; +static NSString* const kDatabasesErrorCodesDatabaseInvalidMessage = + @"Could not access database"; +static NSString* const kDatabasesErrorCodesSqlExecutionExceptionMessage = + @"SQL execution exception: "; diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabasesManager.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabasesManager.h new file mode 100644 index 00000000000..693aac5f633 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabasesManager.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@protocol DatabaseDriver; +@protocol DatabaseDescriptor; +@protocol FlipperConnection; + +@interface DatabasesManager : NSObject + +@property(nonatomic, strong) id connection; + +- (instancetype)init; +- (void)setConnection:(id)connection; +- (BOOL)isConnected; +- (void)addDatabaseDriver:(id)driver; +- (void)removeDatabaseDriver:(id)driver; + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabasesManager.m b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabasesManager.m new file mode 100644 index 00000000000..40b2908f208 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/DatabasesManager.m @@ -0,0 +1,259 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "DatabasesManager.h" +#import +#import +#import +#include +#import "DatabaseDescriptor.h" +#import "DatabaseDescriptorHolder.h" +#import "DatabaseDriver.h" +#import "DatabaseErrorCodes.h" +#import "DatabaseExecuteSql.h" +#import "DatabaseGetTableData.h" +#import "DatabaseGetTableInfo.h" +#import "DatabaseGetTableStructure.h" +#import "ObjectMapper.h" + +@interface DatabasesManager () + +@property(nonatomic, strong) + NSMutableDictionary* + databaseDescriptorHolders; +@property(nonatomic, strong) + NSMutableSet* databaseDescriptorHolderSet; +@property(nonatomic, strong) NSMutableSet>* databaseDrivers; + +@end + +@implementation DatabasesManager + +- (instancetype)init { + self = [super init]; + if (self) { + _databaseDrivers = [NSMutableSet new]; + _databaseDescriptorHolders = [NSMutableDictionary new]; + _databaseDescriptorHolderSet = [NSMutableSet new]; + } + return self; +} + +- (void)setConnection:(id)connection { + _connection = connection; + if (connection) { + [self listenForCommands]; + } +} + +- (BOOL)isConnected { + return _connection != nil; +} + +- (void)listenForCommands { + [self.connection + receive:@"databaseList" + withBlock:^(NSDictionary* params, id responder) { + NSInteger databaseId = 1; + [self.databaseDescriptorHolders removeAllObjects]; + [self.databaseDescriptorHolderSet removeAllObjects]; + + for (id databaseDriver in self.databaseDrivers) { + NSArray>* databaseDescriptorList = + [databaseDriver getDatabases]; + for (id databaseDescriptor in + databaseDescriptorList) { + DatabaseDescriptorHolder* databaseDescriptorHolder = + [[DatabaseDescriptorHolder alloc] + initWithIdentifier:databaseId + databaseDriver:databaseDriver + databaseDescriptor:databaseDescriptor]; + self.databaseDescriptorHolders[@(databaseId)] = + databaseDescriptorHolder; + [self.databaseDescriptorHolderSet + addObject:databaseDescriptorHolder]; + databaseId++; + } + } + + id result = [ObjectMapper + databaseListToFlipperArray:self.databaseDescriptorHolderSet]; + [responder success:result]; + }]; + + [self.connection + receive:@"getTableData" + withBlock:^(NSDictionary* params, id responder) { + DatabaseGetTableDataRequest* request = [DatabaseGetTableDataRequest + getTableDataRequestFromDictionary:params]; + if (!request) { + [DatabasesManager raiseInvalidRequestError:responder]; + return; + } + DatabaseDescriptorHolder* descriptorHolder = + self.databaseDescriptorHolders[@(request.databaseId)]; + if (!descriptorHolder) { + [DatabasesManager raiseDatabaseInvalidError:responder]; + return; + } + + @try { + DatabaseGetTableDataResponse* tableDataResponse = + [descriptorHolder.databaseDriver + getTableDataWithDatabaseDescriptor:descriptorHolder + .databaseDescriptor + forTable:request.table + order:request.order + reverse:request.reverse + start:request.start + count:request.count]; + NSDictionary* response = [ObjectMapper + databaseGetTableDataResponseToDictionary:tableDataResponse]; + [responder success:response]; + } @catch (NSException* exception) { + NSString* reason = exception.reason ?: @"Unknown error"; + NSDictionary* errorResponse = [ObjectMapper + errorWithCode:DatabasesErrorCodesSqlExecutionException + message:[kDatabasesErrorCodesSqlExecutionExceptionMessage + stringByAppendingString:reason]]; + [responder error:errorResponse]; + } + }]; + + [self.connection + receive:@"getTableStructure" + withBlock:^(NSDictionary* params, id responder) { + DatabaseGetTableStructureRequest* request = + [DatabaseGetTableStructureRequest + getTableStructureRequestFromDictionary:params]; + + if (!request) { + [DatabasesManager raiseInvalidRequestError:responder]; + return; + } + DatabaseDescriptorHolder* descriptorHolder = + self.databaseDescriptorHolders[@(request.databaseId)]; + if (!descriptorHolder) { + [DatabasesManager raiseDatabaseInvalidError:responder]; + return; + } + + @try { + DatabaseGetTableStructureResponse* tableStructure = + [descriptorHolder.databaseDriver + getTableStructureWithDatabaseDescriptor: + descriptorHolder.databaseDescriptor + forTable:request.table]; + NSDictionary* response = [ObjectMapper + databaseGetTableStructureResponseToDictionary:tableStructure]; + [responder success:response]; + } @catch (NSException* exception) { + NSString* reason = exception.reason ?: @"Unknown error"; + NSDictionary* errorResponse = [ObjectMapper + errorWithCode:DatabasesErrorCodesSqlExecutionException + message:[kDatabasesErrorCodesSqlExecutionExceptionMessage + stringByAppendingString:reason]]; + [responder error:errorResponse]; + } + }]; + + [self.connection + receive:@"getTableInfo" + withBlock:^(NSDictionary* params, id responder) { + DatabaseGetTableInfoRequest* request = [DatabaseGetTableInfoRequest + getTableInfoRequestFromDictionary:params]; + if (!request) { + [DatabasesManager raiseInvalidRequestError:responder]; + return; + } + DatabaseDescriptorHolder* descriptorHolder = + self.databaseDescriptorHolders[@(request.databaseId)]; + if (!descriptorHolder) { + [DatabasesManager raiseDatabaseInvalidError:responder]; + return; + } + + @try { + DatabaseGetTableInfoResponse* tableInfo = + [descriptorHolder.databaseDriver + getTableInfoWithDatabaseDescriptor:descriptorHolder + .databaseDescriptor + forTable:request.table]; + NSDictionary* response = + [ObjectMapper databaseGetTableInfoResponseToDictionary:tableInfo]; + [responder success:response]; + } @catch (NSException* exception) { + NSString* reason = exception.reason ?: @"Unknown error"; + NSDictionary* errorResponse = [ObjectMapper + errorWithCode:DatabasesErrorCodesSqlExecutionException + message:[kDatabasesErrorCodesSqlExecutionExceptionMessage + stringByAppendingString:reason]]; + [responder error:errorResponse]; + } + }]; + + [self.connection + receive:@"execute" + withBlock:^(NSDictionary* params, id responder) { + DatabaseExecuteSqlRequest* request = [DatabaseExecuteSqlRequest + getExecuteSqlRequestFromDictionary:params]; + if (!request) { + [DatabasesManager raiseInvalidRequestError:responder]; + return; + } + DatabaseDescriptorHolder* descriptorHolder = + self.databaseDescriptorHolders[@(request.databaseId)]; + if (!descriptorHolder) { + [DatabasesManager raiseDatabaseInvalidError:responder]; + return; + } + @try { + DatabaseExecuteSqlResponse* sqlResponse = + [descriptorHolder.databaseDriver executeSQL:request.value]; + NSDictionary* response = + [ObjectMapper databaseExecuteSqlResponseToDictionary:sqlResponse]; + [responder success:response]; + } @catch (NSException* exception) { + NSString* reason = exception.reason ?: @"Unknown error"; + NSDictionary* errorResponse = [ObjectMapper + errorWithCode:DatabasesErrorCodesSqlExecutionException + message:[kDatabasesErrorCodesSqlExecutionExceptionMessage + stringByAppendingString:reason]]; + [responder error:errorResponse]; + } + }]; +} + +- (void)addDatabaseDriver:(id)driver { + if ([self.databaseDrivers containsObject:driver]) { + return; + } + [self.databaseDrivers addObject:driver]; +} + +- (void)removeDatabaseDriver:(id)driver { + if (![self.databaseDrivers containsObject:driver]) { + return; + } + [self.databaseDrivers removeObject:driver]; +} + ++ (void)raiseInvalidRequestError:(id)responder { + NSDictionary* errorResponse = + [ObjectMapper errorWithCode:DatabasesErrorCodesInvalidRequest + message:kDatabasesErrorCodesInvalidRequestMessage]; + [responder error:errorResponse]; +} + ++ (void)raiseDatabaseInvalidError:(id)responder { + NSDictionary* errorResponse = + [ObjectMapper errorWithCode:DatabasesErrorCodesDatabaseInvalid + message:kDatabasesErrorCodesDatabaseInvalidMessage]; + [responder error:errorResponse]; +} + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin.h new file mode 100644 index 00000000000..40fc101f09a --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#if FB_SONARKIT_ENABLED + +#import +#import +#import "DatabaseDriver.h" + +@class DatabasesManager; + +@interface FlipperKitDatabasesPlugin : NSObject +@property(nonatomic, strong) DatabasesManager* databasesManager; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)sharedInstance; +- (void)addDatabaseDriver:(id)driver; +- (void)removeDatabaseDriver:(id)driver; + +@end + +#endif diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin.m b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin.m new file mode 100644 index 00000000000..8ca0dd3b6ec --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin.m @@ -0,0 +1,69 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#if FB_SONARKIT_ENABLED +#import "FlipperKitDatabasesPlugin.h" +#import +#import +#import +#import "DatabaseDriver.h" +#import "DatabasesManager.h" +#import "MockDatabaseDriver.h" + +@interface FlipperKitDatabasesPlugin () +@property(strong, nonatomic) id connection; + +@end + +@implementation FlipperKitDatabasesPlugin + +- (instancetype)init { + if (self = [super init]) { + _databasesManager = [DatabasesManager new]; + } + return self; +} + ++ (instancetype)sharedInstance { + static FlipperKitDatabasesPlugin* sInstance = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sInstance = [FlipperKitDatabasesPlugin new]; + }); + + return sInstance; +} + +- (void)didConnect:(id)connection { + self.connection = connection; + [self.databasesManager setConnection:connection]; +} + +- (void)didDisconnect { + [self.databasesManager setConnection:nil]; +} + +- (NSString*)identifier { + return @"Databases"; +} + +- (BOOL)runInBackground { + return NO; +} + +- (void)addDatabaseDriver:(id)driver { + [self.databasesManager addDatabaseDriver:driver]; +} + +- (void)removeDatabaseDriver:(id)driver { + [self.databasesManager addDatabaseDriver:driver]; +} + +@end + +#endif diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDescriptor.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDescriptor.h new file mode 100644 index 00000000000..763c8e0924f --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDescriptor.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import "DatabaseDescriptor.h" + +@interface MockDatabaseDescriptor : NSObject + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDescriptor.m b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDescriptor.m new file mode 100644 index 00000000000..4dc3d7a0b53 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDescriptor.m @@ -0,0 +1,16 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "MockDatabaseDescriptor.h" + +@implementation MockDatabaseDescriptor + +- (NSString*)name { + return @"MockDatabase"; +} + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDriver.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDriver.h new file mode 100644 index 00000000000..c78aa89e0bf --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDriver.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import + +@interface MockDatabaseDriver : NSObject + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDriver.m b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDriver.m new file mode 100644 index 00000000000..a13b601e5b8 --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/Mock/MockDatabaseDriver.m @@ -0,0 +1,134 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "MockDatabaseDriver.h" +#include +#include +#import "DatabaseExecuteSql.h" +#import "DatabaseGetTableData.h" +#import "DatabaseGetTableInfo.h" +#import "DatabaseGetTableStructure.h" +#import "MockDatabaseDescriptor.h" + +@implementation MockDatabaseDriver + +- (NSArray>*)getDatabases { + MockDatabaseDescriptor* mockDescriptor = + [[MockDatabaseDescriptor alloc] init]; + return @[ mockDescriptor ]; +} + +- (NSArray*)getTableNames: + (id)databaseDescriptor { + return @[ @"MockTable1", @"MockTable2" ]; +} + +- (DatabaseGetTableStructureResponse*) + getTableStructureWithDatabaseDescriptor: + (id)databaseDescriptor + forTable:(NSString*)tableName { + NSMutableArray* structureColumns = + [NSMutableArray arrayWithObjects:@"id", @"name", @"age", nil]; + NSMutableArray*>* structureValues = + [NSMutableArray arrayWithObjects:@[ @"1", @"John", @"25" ], + @[ @"2", @"Jane", @"30" ], + nil]; + NSMutableArray* indexesColumns = [NSMutableArray + arrayWithObjects:@"index_name", @"unique", @"indexed_column_name", nil]; + NSMutableArray*>* indexesValues = [NSMutableArray + arrayWithObjects:@[ @"index_name1", @"false", @"id,name" ], + @[ @"index_name2", @"true", @"age" ], + nil]; + + return [[DatabaseGetTableStructureResponse alloc] + initWithStructureColumns:[structureColumns copy] + structureValues:[structureValues copy] + indexesColumns:[indexesColumns copy] + indexesValues:[indexesValues copy]]; +} + +- (DatabaseGetTableInfoResponse*) + getTableInfoWithDatabaseDescriptor: + (id)databaseDescriptor + forTable:(NSString*)tableName { + return [[DatabaseGetTableInfoResponse alloc] + initWithDefinition:@"This is mocked table definition"]; +} + +- (DatabaseGetTableDataResponse*) + getTableDataWithDatabaseDescriptor: + (id)databaseDescriptor + forTable:(NSString*)tableName + order:(NSString*)order + reverse:(BOOL)reverse + start:(NSInteger)start + count:(NSInteger)count { + NSMutableArray* columns = [NSMutableArray array]; + NSMutableArray* values = [NSMutableArray array]; + NSUInteger numColums = 10; + NSUInteger numRows = 100; + for (int i = 0; i < numColums; i++) { + NSString* columnName = [NSString stringWithFormat:@"column%d", i + 1]; + [columns addObject:columnName]; + } + + for (int i = 0; i < numRows; i++) { + NSMutableArray* valueRow = [NSMutableArray array]; + for (int j = 0; j < numColums; j++) { + [valueRow addObject:[NSString stringWithFormat:@"value%d", j]]; + } + [values addObject:valueRow]; + } + + return [[DatabaseGetTableDataResponse alloc] initWithColumns:[columns copy] + values:[values copy] + start:0 + count:numRows + total:numRows]; +} + +- (DatabaseExecuteSqlResponse*)executeSQL:(NSString*)sql { + // Generate a mock response with a random type + NSString* type; + NSArray* columns = @[ @"id", @"name", @"age" ]; + NSMutableArray* values = [NSMutableArray array]; + NSUInteger numRows = 100; + for (int i = 0; i < numRows; i++) { + NSUInteger randomAge = arc4random_uniform(40); + [values addObject:@[ + @(i), + [NSString stringWithFormat:@"Name %d", i], + @(randomAge) + ]]; + } + + // Randomly select a type + NSArray* types = @[ @"select", @"insert", @"update_delete" ]; + int index = arc4random_uniform((u_int32_t)types.count); + type = types[index]; + + // Set affectedCount and insertedId based on type + NSInteger affectedCount = 0; + NSNumber* insertedId = nil; + if ([type isEqualToString:@"insert"]) { + affectedCount = 1; + insertedId = @(15); + } else if ([type isEqualToString:@"update_delete"]) { + affectedCount = values.count; + } + + DatabaseExecuteSqlResponse* response = + [[DatabaseExecuteSqlResponse alloc] initWithType:type + columns:columns + values:[values copy] + insertedId:insertedId + affectedCount:affectedCount]; + + return response; +} + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/ObjectMapper.h b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/ObjectMapper.h new file mode 100644 index 00000000000..5e083986dea --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/ObjectMapper.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@class DatabaseDescriptorHolder; +@class DatabaseExecuteSqlResponse; +@class DatabaseGetTableDataResponse; +@class DatabaseGetTableInfoResponse; +@class DatabaseGetTableStructureResponse; + +@interface ObjectMapper : NSObject + ++ (NSMutableArray*)databaseListToFlipperArray: + (NSMutableSet*)databaseDescriptorHolderSet; ++ (NSDictionary*)databaseGetTableDataResponseToDictionary: + (DatabaseGetTableDataResponse*)response; ++ (NSDictionary*)databaseGetTableStructureResponseToDictionary: + (DatabaseGetTableStructureResponse*)response; ++ (NSDictionary*)databaseGetTableInfoResponseToDictionary: + (DatabaseGetTableInfoResponse*)response; ++ (NSDictionary*)databaseExecuteSqlResponseToDictionary: + (DatabaseExecuteSqlResponse*)response; ++ (NSDictionary*)errorWithCode:(NSInteger)code message:(NSString*)message; + +@end diff --git a/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/ObjectMapper.m b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/ObjectMapper.m new file mode 100644 index 00000000000..ffb2e54710e --- /dev/null +++ b/iOS/Plugins/FlipperKitDatabasesPlugin/FlipperKitDatabasesPlugin/ObjectMapper.m @@ -0,0 +1,216 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "ObjectMapper.h" +#include +#import "DatabaseDescriptorHolder.h" +#import "DatabaseExecuteSql.h" +#import "DatabaseGetTableData.h" +#import "DatabaseGetTableInfo.h" +#import "DatabaseGetTableStructure.h" + +@implementation ObjectMapper + +static const int MAX_BLOB_LENGTH = 100 * 1024; +static NSString* const UNKNOWN_BLOB_LABEL_FORMAT = @"{%d-byte %@ blob}"; + ++ (NSMutableArray*)databaseListToFlipperArray: + (NSMutableSet*)databaseDescriptorHolderSet { + NSMutableArray* result = [NSMutableArray new]; + + for (DatabaseDescriptorHolder* holder in databaseDescriptorHolderSet) { + NSArray* tables = + [holder.databaseDriver getTableNames:holder.databaseDescriptor]; + NSArray* sortedTableNames = + [tables sortedArrayUsingSelector:@selector(compare:)]; + NSString* idString = [NSString stringWithFormat:@"%ld", holder.identifier]; + + NSDictionary* databaseInfo = @{ + @"id" : idString, + @"name" : holder.databaseDescriptor.name, + @"tables" : sortedTableNames + }; + [result addObject:databaseInfo]; + } + + return result; +} + ++ (NSDictionary*)databaseGetTableDataResponseToDictionary: + (DatabaseGetTableDataResponse*)response { + NSMutableArray* rows = [NSMutableArray array]; + for (NSArray* row in response.values) { + NSMutableArray* rowValues = [NSMutableArray array]; + for (id item in row) { + [rowValues addObject:[self objectAndTypeToFlipperObject:item]]; + } + [rows addObject:rowValues]; + } + + return @{ + @"columns" : response.columns, + @"values" : rows, + @"start" : @(response.start), + @"count" : @(response.count), + @"total" : @(response.total) + }; +} + ++ (NSDictionary*)errorWithCode:(NSInteger)code message:(NSString*)message { + return @{@"code" : @(code), @"message" : message}; +} + ++ (NSDictionary*)databaseGetTableStructureResponseToDictionary: + (DatabaseGetTableStructureResponse*)response { + NSMutableArray* structureValues = [NSMutableArray array]; + for (NSArray* row in response.structureValues) { + NSMutableArray* rowValues = [NSMutableArray array]; + for (id item in row) { + [rowValues addObject:[self objectAndTypeToFlipperObject:item]]; + } + [structureValues addObject:rowValues]; + } + + NSMutableArray* indexesValues = [NSMutableArray array]; + for (NSArray* row in response.indexesValues) { + NSMutableArray* rowValues = [NSMutableArray array]; + for (id item in row) { + [rowValues addObject:[self objectAndTypeToFlipperObject:item]]; + } + [indexesValues addObject:rowValues]; + } + + return @{ + @"structureColumns" : response.structureColumns, + @"structureValues" : structureValues, + @"indexesColumns" : response.indexesColumns, + @"indexesValues" : indexesValues + }; +} + ++ (NSDictionary*)databaseGetTableInfoResponseToDictionary: + (DatabaseGetTableInfoResponse*)response { + return @{ + @"definition" : response.definition, + }; +} + ++ (NSDictionary*)databaseExecuteSqlResponseToDictionary: + (DatabaseExecuteSqlResponse*)response { + NSMutableArray* rows = [NSMutableArray array]; + if (response.values) { + for (NSArray* row in response.values) { + NSMutableArray* rowValues = [NSMutableArray array]; + for (id item in row) { + [rowValues addObject:[self objectAndTypeToFlipperObject:item]]; + } + [rows addObject:rowValues]; + } + } + + NSMutableDictionary* result = [NSMutableDictionary dictionaryWithDictionary:@{ + @"type" : response.type, + @"columns" : response.columns, + @"values" : rows, + @"affectedCount" : @(response.affectedCount) + }]; + + if (response.insertedId) { + result[@"insertedId"] = response.insertedId; + } + + return result; +} + ++ (NSDictionary*)objectAndTypeToFlipperObject:(id)object { + if (!object || [object isKindOfClass:[NSNull class]]) { + return @{@"type" : @"null"}; + } else if ([object isKindOfClass:[NSNumber class]]) { + NSNumber* number = (NSNumber*)object; + NSString* type = [NSString stringWithCString:[number objCType]]; + + if ([type isEqualToString:@"i"]) { + return @{@"type" : @"integer", @"value" : number}; + } else if ([type isEqualToString:@"f"] || [type isEqualToString:@"d"]) { + return @{@"type" : @"float", @"value" : number}; + } else if ([type isEqualToString:@"B"]) { + return @{@"type" : @"boolean", @"value" : number}; + } else { + return @{@"type" : @"integer", @"value" : @([number integerValue])}; + } + + return @{@"type" : @"integer", @"value" : object}; + } else if ([object isKindOfClass:[NSDecimalNumber class]]) { + return @{@"type" : @"float", @"value" : object}; + } else if ([object isKindOfClass:[NSString class]]) { + return @{@"type" : @"string", @"value" : object}; + } else if ([object isKindOfClass:[NSData class]]) { + NSString* blobString = [self blobToString:(NSData*)object]; + return @{@"type" : @"blob", @"value" : blobString}; + } else if ([object isKindOfClass:[NSDictionary class]]) { + // Usualy the dictionary is a Json blob, and we can parse it as string. + NSError* error; + NSData* jsonData = [NSJSONSerialization dataWithJSONObject:object + options:0 + error:&error]; + if (!jsonData) { + NSString* reason = [NSString + stringWithFormat:@"NSDictionary is not in a json format: %@", + [error localizedDescription]]; + @throw [NSException exceptionWithName:@"InvalidArgumentException" + reason:reason + userInfo:nil]; + } + + NSString* jsonString = [[NSString alloc] initWithData:jsonData + encoding:NSUTF8StringEncoding]; + return @{@"type" : @"blob", @"value" : jsonString}; + + } else if ([object isKindOfClass:[NSValue class]]) { + return @{@"type" : @"boolean", @"value" : object}; + } else { + @throw [NSException exceptionWithName:@"InvalidArgumentException" + reason:@"type of Object is invalid" + userInfo:nil]; + } +} + ++ (NSString*)blobToString:(NSData*)data { + const uint8_t* bytes = data.bytes; + uint length = data.length; + + if (length <= MAX_BLOB_LENGTH) { + if ([self fastIsAscii:bytes length:length]) { + NSStringEncoding encoding = NSASCIIStringEncoding; + return [[NSString alloc] initWithBytesNoCopy:(void*)bytes + length:length + encoding:encoding + freeWhenDone:NO]; + } else { + // try UTF-8 + NSStringEncoding encoding = NSUTF8StringEncoding; + return [[NSString alloc] initWithBytesNoCopy:(void*)bytes + length:length + encoding:encoding + freeWhenDone:NO]; + } + } + return + [NSString stringWithFormat:UNKNOWN_BLOB_LABEL_FORMAT, length, @"binary"]; +} + ++ (BOOL)fastIsAscii:(const uint8_t*)bytes length:(NSUInteger)length { + for (int i = 0; i < length; i++) { + uint8_t b = bytes[i]; + if ((b & ~0x7f) != 0) { + return NO; + } + } + return YES; +} + +@end diff --git a/iOS/Sample/Podfile.lock b/iOS/Sample/Podfile.lock index 51c4d4a2182..92508a794d7 100644 --- a/iOS/Sample/Podfile.lock +++ b/iOS/Sample/Podfile.lock @@ -1,6 +1,6 @@ PODS: - CocoaAsyncSocket (7.6.5) - - Flipper (0.210.0): + - Flipper (0.212.0): - Flipper-Folly (~> 2.6) - Flipper-Boost-iOSX (1.76.0.1.11) - Flipper-DoubleConversion (3.2.0.1) @@ -14,50 +14,50 @@ PODS: - OpenSSL-Universal (= 1.1.1100) - Flipper-Glog (0.5.0.5) - Flipper-PeerTalk (0.0.4) - - FlipperKit (0.210.0): - - FlipperKit/Core (= 0.210.0) - - FlipperKit/Core (0.210.0): - - Flipper (~> 0.210.0) + - FlipperKit (0.212.0): + - FlipperKit/Core (= 0.212.0) + - FlipperKit/Core (0.212.0): + - Flipper (~> 0.212.0) - FlipperKit/CppBridge - FlipperKit/FBCxxFollyDynamicConvert - FlipperKit/FBDefines - FlipperKit/FKPortForwarding - SocketRocket (~> 0.7.0) - - FlipperKit/CppBridge (0.210.0): - - Flipper (~> 0.210.0) - - FlipperKit/FBCxxFollyDynamicConvert (0.210.0): + - FlipperKit/CppBridge (0.212.0): + - Flipper (~> 0.212.0) + - FlipperKit/FBCxxFollyDynamicConvert (0.212.0): - Flipper-Folly (~> 2.6) - - FlipperKit/FBDefines (0.210.0) - - FlipperKit/FKPortForwarding (0.210.0): + - FlipperKit/FBDefines (0.212.0) + - FlipperKit/FKPortForwarding (0.212.0): - CocoaAsyncSocket (~> 7.6) - Flipper-PeerTalk (~> 0.0.4) - - FlipperKit/FlipperKitExamplePlugin (0.210.0): + - FlipperKit/FlipperKitExamplePlugin (0.212.0): - FlipperKit/Core - - FlipperKit/FlipperKitHighlightOverlay (0.210.0) - - FlipperKit/FlipperKitLayoutHelpers (0.210.0): + - FlipperKit/FlipperKitHighlightOverlay (0.212.0) + - FlipperKit/FlipperKitLayoutHelpers (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutTextSearchable - - FlipperKit/FlipperKitLayoutIOSDescriptors (0.210.0): + - FlipperKit/FlipperKitLayoutIOSDescriptors (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutHelpers - - FlipperKit/FlipperKitLayoutPlugin (0.210.0): + - FlipperKit/FlipperKitLayoutPlugin (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutHelpers - FlipperKit/FlipperKitLayoutIOSDescriptors - FlipperKit/FlipperKitLayoutTextSearchable - - FlipperKit/FlipperKitLayoutTextSearchable (0.210.0) - - FlipperKit/FlipperKitNetworkPlugin (0.210.0): + - FlipperKit/FlipperKitLayoutTextSearchable (0.212.0) + - FlipperKit/FlipperKitNetworkPlugin (0.212.0): - FlipperKit/Core - - FlipperKit/FlipperKitReactPlugin (0.210.0): + - FlipperKit/FlipperKitReactPlugin (0.212.0): - FlipperKit/Core - - FlipperKit/FlipperKitUIDebuggerPlugin (0.210.0): + - FlipperKit/FlipperKitUIDebuggerPlugin (0.212.0): - FlipperKit/Core - - FlipperKit/FlipperKitUserDefaultsPlugin (0.210.0): + - FlipperKit/FlipperKitUserDefaultsPlugin (0.212.0): - FlipperKit/Core - - FlipperKit/SKIOSNetworkPlugin (0.210.0): + - FlipperKit/SKIOSNetworkPlugin (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitNetworkPlugin - libevent (2.1.12) @@ -104,14 +104,14 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 - Flipper: 4a5b2c2c6ac926d6881ead86c1b5411fc79da46e + Flipper: b7a3d90634c855fece9d491ca69f682f1244984f Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3 Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446 Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 - FlipperKit: c2aabe903823302c655ebbc33e1cc59d275fdcaa + FlipperKit: 73b2e0c1ed75801151dab992313b6b1951b67446 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d diff --git a/iOS/SampleSwift/Podfile.lock b/iOS/SampleSwift/Podfile.lock index 7d1b5d0dc85..56fb3b378a7 100644 --- a/iOS/SampleSwift/Podfile.lock +++ b/iOS/SampleSwift/Podfile.lock @@ -1,7 +1,7 @@ PODS: - boost-for-react-native (1.63.0) - CocoaAsyncSocket (7.6.5) - - Flipper (0.210.0): + - Flipper (0.212.0): - Flipper-Folly (~> 2.6) - Flipper-Boost-iOSX (1.76.0.1.11) - Flipper-DoubleConversion (3.2.0.1) @@ -15,46 +15,46 @@ PODS: - OpenSSL-Universal (= 1.1.1100) - Flipper-Glog (0.5.0.5) - Flipper-PeerTalk (0.0.4) - - FlipperKit (0.210.0): - - FlipperKit/Core (= 0.210.0) - - FlipperKit/Core (0.210.0): - - Flipper (~> 0.210.0) + - FlipperKit (0.212.0): + - FlipperKit/Core (= 0.212.0) + - FlipperKit/Core (0.212.0): + - Flipper (~> 0.212.0) - FlipperKit/CppBridge - FlipperKit/FBCxxFollyDynamicConvert - FlipperKit/FBDefines - FlipperKit/FKPortForwarding - SocketRocket (~> 0.7.0) - - FlipperKit/CppBridge (0.210.0): - - Flipper (~> 0.210.0) - - FlipperKit/FBCxxFollyDynamicConvert (0.210.0): + - FlipperKit/CppBridge (0.212.0): + - Flipper (~> 0.212.0) + - FlipperKit/FBCxxFollyDynamicConvert (0.212.0): - Flipper-Folly (~> 2.6) - - FlipperKit/FBDefines (0.210.0) - - FlipperKit/FKPortForwarding (0.210.0): + - FlipperKit/FBDefines (0.212.0) + - FlipperKit/FKPortForwarding (0.212.0): - CocoaAsyncSocket (~> 7.6) - Flipper-PeerTalk (~> 0.0.4) - - FlipperKit/FlipperKitExamplePlugin (0.210.0): + - FlipperKit/FlipperKitExamplePlugin (0.212.0): - FlipperKit/Core - - FlipperKit/FlipperKitHighlightOverlay (0.210.0) - - FlipperKit/FlipperKitLayoutHelpers (0.210.0): + - FlipperKit/FlipperKitHighlightOverlay (0.212.0) + - FlipperKit/FlipperKitLayoutHelpers (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutTextSearchable - - FlipperKit/FlipperKitLayoutIOSDescriptors (0.210.0): + - FlipperKit/FlipperKitLayoutIOSDescriptors (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutHelpers - - FlipperKit/FlipperKitLayoutPlugin (0.210.0): + - FlipperKit/FlipperKitLayoutPlugin (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutHelpers - FlipperKit/FlipperKitLayoutIOSDescriptors - FlipperKit/FlipperKitLayoutTextSearchable - - FlipperKit/FlipperKitLayoutTextSearchable (0.210.0) - - FlipperKit/FlipperKitNetworkPlugin (0.210.0): + - FlipperKit/FlipperKitLayoutTextSearchable (0.212.0) + - FlipperKit/FlipperKitNetworkPlugin (0.212.0): - FlipperKit/Core - - FlipperKit/FlipperKitUserDefaultsPlugin (0.210.0): + - FlipperKit/FlipperKitUserDefaultsPlugin (0.212.0): - FlipperKit/Core - - FlipperKit/SKIOSNetworkPlugin (0.210.0): + - FlipperKit/SKIOSNetworkPlugin (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitNetworkPlugin - libevent (2.1.12) @@ -100,14 +100,14 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 - Flipper: 4a5b2c2c6ac926d6881ead86c1b5411fc79da46e + Flipper: b7a3d90634c855fece9d491ca69f682f1244984f Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3 Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446 Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 - FlipperKit: c2aabe903823302c655ebbc33e1cc59d275fdcaa + FlipperKit: 73b2e0c1ed75801151dab992313b6b1951b67446 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d diff --git a/iOS/Tutorial/Podfile b/iOS/Tutorial/Podfile index 0711000481d..8486dc07e24 100644 --- a/iOS/Tutorial/Podfile +++ b/iOS/Tutorial/Podfile @@ -1,6 +1,6 @@ project 'Tutorial.xcodeproj' swift_version = "4.1" -flipperkit_version = '0.210.0' +flipperkit_version = '0.212.0' use_frameworks! target 'Tutorial' do diff --git a/iOS/Tutorial/Podfile.lock b/iOS/Tutorial/Podfile.lock index 8e6ca565be9..3861b280fcd 100644 --- a/iOS/Tutorial/Podfile.lock +++ b/iOS/Tutorial/Podfile.lock @@ -3,7 +3,7 @@ PODS: - ComponentKit (0.31): - RenderCore (= 0.31) - Yoga (~> 1.14) - - Flipper (0.210.0): + - Flipper (0.212.0): - Flipper-Folly (~> 2.6) - Flipper-Boost-iOSX (1.76.0.1.11) - Flipper-DoubleConversion (3.2.0.1) @@ -17,25 +17,25 @@ PODS: - OpenSSL-Universal (= 1.1.1100) - Flipper-Glog (0.5.0.5) - Flipper-PeerTalk (0.0.4) - - FlipperKit (0.210.0): - - FlipperKit/Core (= 0.210.0) - - FlipperKit/Core (0.210.0): - - Flipper (~> 0.210.0) + - FlipperKit (0.212.0): + - FlipperKit/Core (= 0.212.0) + - FlipperKit/Core (0.212.0): + - Flipper (~> 0.212.0) - FlipperKit/CppBridge - FlipperKit/FBCxxFollyDynamicConvert - FlipperKit/FBDefines - FlipperKit/FKPortForwarding - SocketRocket (~> 0.7.0) - - FlipperKit/CppBridge (0.210.0): - - Flipper (~> 0.210.0) - - FlipperKit/FBCxxFollyDynamicConvert (0.210.0): + - FlipperKit/CppBridge (0.212.0): + - Flipper (~> 0.212.0) + - FlipperKit/FBCxxFollyDynamicConvert (0.212.0): - Flipper-Folly (~> 2.6) - - FlipperKit/FBDefines (0.210.0) - - FlipperKit/FKPortForwarding (0.210.0): + - FlipperKit/FBDefines (0.212.0) + - FlipperKit/FKPortForwarding (0.212.0): - CocoaAsyncSocket (~> 7.6) - Flipper-PeerTalk (~> 0.0.4) - - FlipperKit/FlipperKitHighlightOverlay (0.210.0) - - FlipperKit/FlipperKitLayoutComponentKitSupport (0.210.0): + - FlipperKit/FlipperKitHighlightOverlay (0.212.0) + - FlipperKit/FlipperKitLayoutComponentKitSupport (0.212.0): - ComponentKit (= 0.31) - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay @@ -43,26 +43,26 @@ PODS: - FlipperKit/FlipperKitLayoutPlugin - FlipperKit/FlipperKitLayoutTextSearchable - RenderCore (= 0.31) - - FlipperKit/FlipperKitLayoutHelpers (0.210.0): + - FlipperKit/FlipperKitLayoutHelpers (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutTextSearchable - - FlipperKit/FlipperKitLayoutIOSDescriptors (0.210.0): + - FlipperKit/FlipperKitLayoutIOSDescriptors (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutHelpers - - FlipperKit/FlipperKitLayoutPlugin (0.210.0): + - FlipperKit/FlipperKitLayoutPlugin (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutHelpers - FlipperKit/FlipperKitLayoutIOSDescriptors - FlipperKit/FlipperKitLayoutTextSearchable - - FlipperKit/FlipperKitLayoutTextSearchable (0.210.0) - - FlipperKit/FlipperKitNetworkPlugin (0.210.0): + - FlipperKit/FlipperKitLayoutTextSearchable (0.212.0) + - FlipperKit/FlipperKitNetworkPlugin (0.212.0): - FlipperKit/Core - - FlipperKit/FlipperKitUserDefaultsPlugin (0.210.0): + - FlipperKit/FlipperKitUserDefaultsPlugin (0.212.0): - FlipperKit/Core - - FlipperKit/SKIOSNetworkPlugin (0.210.0): + - FlipperKit/SKIOSNetworkPlugin (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitNetworkPlugin - libevent (2.1.12) @@ -72,10 +72,10 @@ PODS: - Yoga (1.14.0) DEPENDENCIES: - - FlipperKit (~> 0.210.0) - - FlipperKit/FlipperKitLayoutComponentKitSupport (~> 0.210.0) - - FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.210.0) - - FlipperKit/SKIOSNetworkPlugin (~> 0.210.0) + - FlipperKit (~> 0.212.0) + - FlipperKit/FlipperKitLayoutComponentKitSupport (~> 0.212.0) + - FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.212.0) + - FlipperKit/SKIOSNetworkPlugin (~> 0.212.0) SPEC REPOS: trunk: @@ -98,20 +98,20 @@ SPEC REPOS: SPEC CHECKSUMS: CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 ComponentKit: 7bf7048b9814afc6b6641645a14177f95fd9b9ae - Flipper: 4a5b2c2c6ac926d6881ead86c1b5411fc79da46e + Flipper: b7a3d90634c855fece9d491ca69f682f1244984f Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3 Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446 Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 - FlipperKit: c2aabe903823302c655ebbc33e1cc59d275fdcaa + FlipperKit: 73b2e0c1ed75801151dab992313b6b1951b67446 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RenderCore: 090beb17b5bff80b86929a7ceb49df789923d23a SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d Yoga: cff67a400f6b74dc38eb0bad4f156673d9aa980c -PODFILE CHECKSUM: 1c66a17eebb0e2f5caefa9b800082c6656cdfdf2 +PODFILE CHECKSUM: c6cb86baae89a95f90a831dc0a3f0451b2e2ee28 COCOAPODS: 1.12.1 diff --git a/js/js-flipper/package.json b/js/js-flipper/package.json index 29440aee5da..9d621d8e51b 100644 --- a/js/js-flipper/package.json +++ b/js/js-flipper/package.json @@ -1,7 +1,7 @@ { "name": "js-flipper", "title": "JS Flipper Bindings for Web-Socket based clients", - "version": "0.210.1", + "version": "0.212.0", "main": "lib/index.js", "browser": { "os": false @@ -39,31 +39,31 @@ "licenseFilename": "LICENSE", "readmeFilename": "README.md", "devDependencies": { - "@babel/core": "^7.22.9", - "@babel/eslint-parser": "7.22.9", + "@babel/core": "^7.22.10", + "@babel/eslint-parser": "7.22.10", "@types/jest": "^29.5.3", - "@types/node": "^20.4.2", - "@types/sinon": "^10.0.15", + "@types/node": "^20.5.0", + "@types/sinon": "^10.0.16", "@types/ws": "^8.5.5", - "@typescript-eslint/eslint-plugin": "6.1.0", - "@typescript-eslint/parser": "6.1.0", + "@typescript-eslint/eslint-plugin": "6.4.0", + "@typescript-eslint/parser": "6.4.0", "ansi-to-html": "^0.7.2", "cross-env": "^7.0.3", - "eslint": "8.45.0", + "eslint": "8.47.0", "eslint-config-fbjs": "^4.0.0", - "eslint-config-prettier": "^8.8.0", - "eslint-import-resolver-typescript": "^3.5.5", + "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": "^3.6.0", "eslint-plugin-babel": "^5.3.0", - "eslint-plugin-ft-flow": "^2.0.3", + "eslint-plugin-ft-flow": "^3.0.0", "eslint-plugin-header": "^3.0.0", - "eslint-plugin-import": "^2.27.5", + "eslint-plugin-import": "^2.28.0", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^5.0.0", - "eslint-plugin-react": "^7.33.0", + "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.5.0", - "jest": "^29.6.1", - "prettier": "^3.0.0", + "jest": "^29.6.2", + "prettier": "^3.0.2", "sinon": "^15.2.0", "ts-jest": "^29.1.0", "typescript": "^5.1.6", diff --git a/js/js-flipper/yarn.lock b/js/js-flipper/yarn.lock index 510e3ac3fd4..3f045604a65 100644 --- a/js/js-flipper/yarn.lock +++ b/js/js-flipper/yarn.lock @@ -22,6 +22,14 @@ dependencies: "@babel/highlight" "^7.18.6" +"@babel/code-frame@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.10.tgz#1c20e612b768fefa75f6e90d6ecb86329247f0a3" + integrity sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA== + dependencies: + "@babel/highlight" "^7.22.10" + chalk "^2.4.2" + "@babel/code-frame@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" @@ -60,31 +68,31 @@ json5 "^2.2.1" semver "^6.3.0" -"@babel/core@^7.22.9": - version "7.22.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.9.tgz#bd96492c68822198f33e8a256061da3cf391f58f" - integrity sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w== +"@babel/core@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.10.tgz#aad442c7bcd1582252cb4576747ace35bc122f35" + integrity sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.9" - "@babel/helper-compilation-targets" "^7.22.9" + "@babel/code-frame" "^7.22.10" + "@babel/generator" "^7.22.10" + "@babel/helper-compilation-targets" "^7.22.10" "@babel/helper-module-transforms" "^7.22.9" - "@babel/helpers" "^7.22.6" - "@babel/parser" "^7.22.7" + "@babel/helpers" "^7.22.10" + "@babel/parser" "^7.22.10" "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.8" - "@babel/types" "^7.22.5" + "@babel/traverse" "^7.22.10" + "@babel/types" "^7.22.10" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.2" semver "^6.3.1" -"@babel/eslint-parser@7.22.9": - version "7.22.9" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.22.9.tgz#75f8aa978d1e76c87cc6f26c1ea16ae58804d390" - integrity sha512-xdMkt39/nviO/4vpVdrEYPwXCsYIXSSAr6mC7WQsNIlGnuxKyKE7GZjalcnbSWiC4OXGNNN3UQPeHfjSC6sTDA== +"@babel/eslint-parser@7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.22.10.tgz#bfdf3d1b32ad573fe7c1c3447e0b485e3a41fd09" + integrity sha512-0J8DNPRXQRLeR9rPaUMM3fA+RbixjnVLe/MRMYCkp3hzgsSuxCHQ8NN8xQG1wIHKJ4a1DTROTvFJdW+B5/eOsg== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" eslint-visitor-keys "^2.1.0" @@ -99,12 +107,12 @@ "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" -"@babel/generator@^7.22.7", "@babel/generator@^7.22.9": - version "7.22.9" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d" - integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw== +"@babel/generator@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.10.tgz#c92254361f398e160645ac58831069707382b722" + integrity sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A== dependencies: - "@babel/types" "^7.22.5" + "@babel/types" "^7.22.10" "@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" @@ -119,10 +127,10 @@ browserslist "^4.21.3" semver "^6.3.0" -"@babel/helper-compilation-targets@^7.22.9": - version "7.22.9" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz#f9d0a7aaaa7cd32a3f31c9316a69f5a9bcacb892" - integrity sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw== +"@babel/helper-compilation-targets@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz#01d648bbc25dd88f513d862ee0df27b7d4e67024" + integrity sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q== dependencies: "@babel/compat-data" "^7.22.9" "@babel/helper-validator-option" "^7.22.5" @@ -281,14 +289,14 @@ "@babel/traverse" "^7.20.5" "@babel/types" "^7.20.5" -"@babel/helpers@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.6.tgz#8e61d3395a4f0c5a8060f309fb008200969b5ecd" - integrity sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA== +"@babel/helpers@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.10.tgz#ae6005c539dfbcb5cd71fb51bfc8a52ba63bc37a" + integrity sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw== dependencies: "@babel/template" "^7.22.5" - "@babel/traverse" "^7.22.6" - "@babel/types" "^7.22.5" + "@babel/traverse" "^7.22.10" + "@babel/types" "^7.22.10" "@babel/highlight@^7.18.6": version "7.18.6" @@ -299,6 +307,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.10.tgz#02a3f6d8c1cb4521b2fd0ab0da8f4739936137d7" + integrity sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ== + dependencies: + "@babel/helper-validator-identifier" "^7.22.5" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@babel/highlight@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" @@ -313,7 +330,12 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.5.tgz#7f3c7335fe417665d929f34ae5dceae4c04015e8" integrity sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA== -"@babel/parser@^7.22.5", "@babel/parser@^7.22.7": +"@babel/parser@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.10.tgz#e37634f9a12a1716136c44624ef54283cabd3f55" + integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ== + +"@babel/parser@^7.22.5": version "7.22.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae" integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q== @@ -457,19 +479,19 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8": - version "7.22.8" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e" - integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw== +"@babel/traverse@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.10.tgz#20252acb240e746d27c2e82b4484f199cf8141aa" + integrity sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig== dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.7" + "@babel/code-frame" "^7.22.10" + "@babel/generator" "^7.22.10" "@babel/helper-environment-visitor" "^7.22.5" "@babel/helper-function-name" "^7.22.5" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.22.7" - "@babel/types" "^7.22.5" + "@babel/parser" "^7.22.10" + "@babel/types" "^7.22.10" debug "^4.1.0" globals "^11.1.0" @@ -482,6 +504,15 @@ "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" +"@babel/types@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.10.tgz#4a9e76446048f2c66982d1a989dd12b8a2d2dc03" + integrity sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" + to-fast-properties "^2.0.0" + "@babel/types@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" @@ -510,20 +541,20 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.4.0.tgz#3e61c564fcd6b921cb789838631c5ee44df09403" - integrity sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ== - "@eslint-community/regexpp@^4.5.1": version "4.5.1" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== -"@eslint/eslintrc@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.0.tgz#82256f164cc9e0b59669efc19d57f8092706841d" - integrity sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A== +"@eslint-community/regexpp@^4.6.1": + version "4.6.2" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.6.2.tgz#1816b5f6948029c5eaacb0703b850ee0cb37d8f8" + integrity sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw== + +"@eslint/eslintrc@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" + integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -535,10 +566,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.44.0": - version "8.44.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.44.0.tgz#961a5903c74139390478bdc808bcde3fc45ab7af" - integrity sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw== +"@eslint/js@^8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.47.0.tgz#5478fdf443ff8158f9de171c704ae45308696c7d" + integrity sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og== "@humanwhocodes/config-array@^0.11.10": version "0.11.10" @@ -575,27 +606,27 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.6.1.tgz#b48ba7b9c34b51483e6d590f46e5837f1ab5f639" - integrity sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q== +"@jest/console@^29.6.2": + version "29.6.2" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.6.2.tgz#bf1d4101347c23e07c029a1b1ae07d550f5cc541" + integrity sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w== dependencies: "@jest/types" "^29.6.1" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^29.6.1" - jest-util "^29.6.1" + jest-message-util "^29.6.2" + jest-util "^29.6.2" slash "^3.0.0" -"@jest/core@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.6.1.tgz#fac0d9ddf320490c93356ba201451825231e95f6" - integrity sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ== +"@jest/core@^29.6.2": + version "29.6.2" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.6.2.tgz#6f2d1dbe8aa0265fcd4fb8082ae1952f148209c8" + integrity sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg== dependencies: - "@jest/console" "^29.6.1" - "@jest/reporters" "^29.6.1" - "@jest/test-result" "^29.6.1" - "@jest/transform" "^29.6.1" + "@jest/console" "^29.6.2" + "@jest/reporters" "^29.6.2" + "@jest/test-result" "^29.6.2" + "@jest/transform" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" ansi-escapes "^4.2.1" @@ -604,32 +635,32 @@ exit "^0.1.2" graceful-fs "^4.2.9" jest-changed-files "^29.5.0" - jest-config "^29.6.1" - jest-haste-map "^29.6.1" - jest-message-util "^29.6.1" + jest-config "^29.6.2" + jest-haste-map "^29.6.2" + jest-message-util "^29.6.2" jest-regex-util "^29.4.3" - jest-resolve "^29.6.1" - jest-resolve-dependencies "^29.6.1" - jest-runner "^29.6.1" - jest-runtime "^29.6.1" - jest-snapshot "^29.6.1" - jest-util "^29.6.1" - jest-validate "^29.6.1" - jest-watcher "^29.6.1" + jest-resolve "^29.6.2" + jest-resolve-dependencies "^29.6.2" + jest-runner "^29.6.2" + jest-runtime "^29.6.2" + jest-snapshot "^29.6.2" + jest-util "^29.6.2" + jest-validate "^29.6.2" + jest-watcher "^29.6.2" micromatch "^4.0.4" - pretty-format "^29.6.1" + pretty-format "^29.6.2" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.6.1.tgz#ee358fff2f68168394b4a50f18c68278a21fe82f" - integrity sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A== +"@jest/environment@^29.6.2": + version "29.6.2" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.6.2.tgz#794c0f769d85e7553439d107d3f43186dc6874a9" + integrity sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q== dependencies: - "@jest/fake-timers" "^29.6.1" + "@jest/fake-timers" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" - jest-mock "^29.6.1" + jest-mock "^29.6.2" "@jest/expect-utils@^29.4.2": version "29.4.2" @@ -638,52 +669,52 @@ dependencies: jest-get-type "^29.4.2" -"@jest/expect-utils@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.6.1.tgz#ab83b27a15cdd203fe5f68230ea22767d5c3acc5" - integrity sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw== +"@jest/expect-utils@^29.6.2": + version "29.6.2" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.6.2.tgz#1b97f290d0185d264dd9fdec7567a14a38a90534" + integrity sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg== dependencies: jest-get-type "^29.4.3" -"@jest/expect@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.6.1.tgz#fef18265188f6a97601f1ea0a2912d81a85b4657" - integrity sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg== +"@jest/expect@^29.6.2": + version "29.6.2" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.6.2.tgz#5a2ad58bb345165d9ce0a1845bbf873c480a4b28" + integrity sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg== dependencies: - expect "^29.6.1" - jest-snapshot "^29.6.1" + expect "^29.6.2" + jest-snapshot "^29.6.2" -"@jest/fake-timers@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.6.1.tgz#c773efddbc61e1d2efcccac008139f621de57c69" - integrity sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg== +"@jest/fake-timers@^29.6.2": + version "29.6.2" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.6.2.tgz#fe9d43c5e4b1b901168fe6f46f861b3e652a2df4" + integrity sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA== dependencies: "@jest/types" "^29.6.1" "@sinonjs/fake-timers" "^10.0.2" "@types/node" "*" - jest-message-util "^29.6.1" - jest-mock "^29.6.1" - jest-util "^29.6.1" + jest-message-util "^29.6.2" + jest-mock "^29.6.2" + jest-util "^29.6.2" -"@jest/globals@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.6.1.tgz#c8a8923e05efd757308082cc22893d82b8aa138f" - integrity sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A== +"@jest/globals@^29.6.2": + version "29.6.2" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.6.2.tgz#74af81b9249122cc46f1eb25793617eec69bf21a" + integrity sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw== dependencies: - "@jest/environment" "^29.6.1" - "@jest/expect" "^29.6.1" + "@jest/environment" "^29.6.2" + "@jest/expect" "^29.6.2" "@jest/types" "^29.6.1" - jest-mock "^29.6.1" + jest-mock "^29.6.2" -"@jest/reporters@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.6.1.tgz#3325a89c9ead3cf97ad93df3a427549d16179863" - integrity sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA== +"@jest/reporters@^29.6.2": + version "29.6.2" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.6.2.tgz#524afe1d76da33d31309c2c4a2c8062d0c48780a" + integrity sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.6.1" - "@jest/test-result" "^29.6.1" - "@jest/transform" "^29.6.1" + "@jest/console" "^29.6.2" + "@jest/test-result" "^29.6.2" + "@jest/transform" "^29.6.2" "@jest/types" "^29.6.1" "@jridgewell/trace-mapping" "^0.3.18" "@types/node" "*" @@ -697,9 +728,9 @@ istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.1.3" - jest-message-util "^29.6.1" - jest-util "^29.6.1" - jest-worker "^29.6.1" + jest-message-util "^29.6.2" + jest-util "^29.6.2" + jest-worker "^29.6.2" slash "^3.0.0" string-length "^4.0.1" strip-ansi "^6.0.0" @@ -735,30 +766,30 @@ callsites "^3.0.0" graceful-fs "^4.2.9" -"@jest/test-result@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.6.1.tgz#850e565a3f58ee8ca6ec424db00cb0f2d83c36ba" - integrity sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw== +"@jest/test-result@^29.6.2": + version "29.6.2" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.6.2.tgz#fdd11583cd1608e4db3114e8f0cce277bf7a32ed" + integrity sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw== dependencies: - "@jest/console" "^29.6.1" + "@jest/console" "^29.6.2" "@jest/types" "^29.6.1" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz#e3e582ee074dd24ea9687d7d1aaf05ee3a9b068e" - integrity sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg== +"@jest/test-sequencer@^29.6.2": + version "29.6.2" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz#585eff07a68dd75225a7eacf319780cb9f6b9bf4" + integrity sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw== dependencies: - "@jest/test-result" "^29.6.1" + "@jest/test-result" "^29.6.2" graceful-fs "^4.2.9" - jest-haste-map "^29.6.1" + jest-haste-map "^29.6.2" slash "^3.0.0" -"@jest/transform@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.6.1.tgz#acb5606019a197cb99beda3c05404b851f441c92" - integrity sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg== +"@jest/transform@^29.6.2": + version "29.6.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.6.2.tgz#522901ebbb211af08835bc3bcdf765ab778094e3" + integrity sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg== dependencies: "@babel/core" "^7.11.6" "@jest/types" "^29.6.1" @@ -768,9 +799,9 @@ convert-source-map "^2.0.0" fast-json-stable-stringify "^2.1.0" graceful-fs "^4.2.9" - jest-haste-map "^29.6.1" + jest-haste-map "^29.6.2" jest-regex-util "^29.4.3" - jest-util "^29.6.1" + jest-util "^29.6.2" micromatch "^4.0.4" pirates "^4.0.4" slash "^3.0.0" @@ -1050,25 +1081,20 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.3.tgz#4e4a95b6fe44014563ceb514b2598b3e623d1c98" integrity sha512-6qKpDtoaYLM+5+AFChLhHermMQxc3TOEFIDzrZLPRGHPrLEwqFkkT5Kx3ju05g6X7uDPazz3jHbKPX0KzCjntg== -"@types/node@^20.4.2": - version "20.4.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.2.tgz#129cc9ae69f93824f92fac653eebfb4812ab4af9" - integrity sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw== - -"@types/prettier@^2.1.5": - version "2.6.4" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.4.tgz#ad899dad022bab6b5a9f0a0fe67c2f7a4a8950ed" - integrity sha512-fOwvpvQYStpb/zHMx0Cauwywu9yLDmzWiiQBC7gJyq5tYLUXFZvDG7VK1B7WBxxjBJNKFOZ0zLoOQn8vmATbhw== +"@types/node@^20.5.0": + version "20.5.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.0.tgz#7fc8636d5f1aaa3b21e6245e97d56b7f56702313" + integrity sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q== "@types/semver@^7.5.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== -"@types/sinon@^10.0.15": - version "10.0.15" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.15.tgz#513fded9c3cf85e589bbfefbf02b2a0541186b48" - integrity sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ== +"@types/sinon@^10.0.16": + version "10.0.16" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.16.tgz#4bf10313bd9aa8eef1e50ec9f4decd3dd455b4d3" + integrity sha512-j2Du5SYpXZjJVJtXBokASpPRj+e2z+VUhCPHmM6WMfe3dpHu6iVKJMU6AiBcMp/XTAYnEj6Wc1trJUWwZ0QaAQ== dependencies: "@types/sinonjs__fake-timers" "*" @@ -1101,90 +1127,89 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.1.0.tgz#96f3ca6615717659d06c9f7161a1d14ab0c49c66" - integrity sha512-qg7Bm5TyP/I7iilGyp6DRqqkt8na00lI6HbjWZObgk3FFSzH5ypRwAHXJhJkwiRtTcfn+xYQIMOR5kJgpo6upw== +"@typescript-eslint/eslint-plugin@6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.0.tgz#53428b616f7d80fe879f45a08f11cc0f0b62cf13" + integrity sha512-62o2Hmc7Gs3p8SLfbXcipjWAa6qk2wZGChXG2JbBtYpwSRmti/9KHLqfbLs9uDigOexG+3PaQ9G2g3201FWLKg== dependencies: "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.1.0" - "@typescript-eslint/type-utils" "6.1.0" - "@typescript-eslint/utils" "6.1.0" - "@typescript-eslint/visitor-keys" "6.1.0" + "@typescript-eslint/scope-manager" "6.4.0" + "@typescript-eslint/type-utils" "6.4.0" + "@typescript-eslint/utils" "6.4.0" + "@typescript-eslint/visitor-keys" "6.4.0" debug "^4.3.4" graphemer "^1.4.0" ignore "^5.2.4" natural-compare "^1.4.0" - natural-compare-lite "^1.4.0" semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/parser@6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.1.0.tgz#3135bf65dca5340d8650703eb8cb83113e156ee5" - integrity sha512-hIzCPvX4vDs4qL07SYzyomamcs2/tQYXg5DtdAfj35AyJ5PIUqhsLf4YrEIFzZcND7R2E8tpQIZKayxg8/6Wbw== +"@typescript-eslint/parser@6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.4.0.tgz#47e7c6e22ff1248e8675d95f488890484de67600" + integrity sha512-I1Ah1irl033uxjxO9Xql7+biL3YD7w9IU8zF+xlzD/YxY6a4b7DYA08PXUUCbm2sEljwJF6ERFy2kTGAGcNilg== dependencies: - "@typescript-eslint/scope-manager" "6.1.0" - "@typescript-eslint/types" "6.1.0" - "@typescript-eslint/typescript-estree" "6.1.0" - "@typescript-eslint/visitor-keys" "6.1.0" + "@typescript-eslint/scope-manager" "6.4.0" + "@typescript-eslint/types" "6.4.0" + "@typescript-eslint/typescript-estree" "6.4.0" + "@typescript-eslint/visitor-keys" "6.4.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz#a6cdbe11630614f8c04867858a42dd56590796ed" - integrity sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw== +"@typescript-eslint/scope-manager@6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.4.0.tgz#3048e4262ba3eafa4e2e69b08912d9037ec646ae" + integrity sha512-TUS7vaKkPWDVvl7GDNHFQMsMruD+zhkd3SdVW0d7b+7Zo+bd/hXJQ8nsiUZMi1jloWo6c9qt3B7Sqo+flC1nig== dependencies: - "@typescript-eslint/types" "6.1.0" - "@typescript-eslint/visitor-keys" "6.1.0" + "@typescript-eslint/types" "6.4.0" + "@typescript-eslint/visitor-keys" "6.4.0" -"@typescript-eslint/type-utils@6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.1.0.tgz#21cc6c3bc1980b03f9eb4e64580d0c5be6f08215" - integrity sha512-kFXBx6QWS1ZZ5Ni89TyT1X9Ag6RXVIVhqDs0vZE/jUeWlBv/ixq2diua6G7ece6+fXw3TvNRxP77/5mOMusx2w== +"@typescript-eslint/type-utils@6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.4.0.tgz#c8ac92716ed6a9d5443aa3e342910355b0796ba0" + integrity sha512-TvqrUFFyGY0cX3WgDHcdl2/mMCWCDv/0thTtx/ODMY1QhEiyFtv/OlLaNIiYLwRpAxAtOLOY9SUf1H3Q3dlwAg== dependencies: - "@typescript-eslint/typescript-estree" "6.1.0" - "@typescript-eslint/utils" "6.1.0" + "@typescript-eslint/typescript-estree" "6.4.0" + "@typescript-eslint/utils" "6.4.0" debug "^4.3.4" ts-api-utils "^1.0.1" -"@typescript-eslint/types@6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.1.0.tgz#2d607c62827bb416ada5c96ebfa2ef84e45a8dfa" - integrity sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ== +"@typescript-eslint/types@6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.4.0.tgz#5b109a59a805f0d8d375895e42d9e5f0037f66ee" + integrity sha512-+FV9kVFrS7w78YtzkIsNSoYsnOtrYVnKWSTVXoL1761CsCRv5wpDOINgsXpxD67YCLZtVQekDDyaxfjVWUJmmg== -"@typescript-eslint/typescript-estree@6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz#ea382f6482ba698d7e993a88ce5391ea7a66c33d" - integrity sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg== +"@typescript-eslint/typescript-estree@6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.0.tgz#3c58d20632db93fec3d6ab902acbedf593d37276" + integrity sha512-iDPJArf/K2sxvjOR6skeUCNgHR/tCQXBsa+ee1/clRKr3olZjZ/dSkXPZjG6YkPtnW6p5D1egeEPMCW6Gn4yLA== dependencies: - "@typescript-eslint/types" "6.1.0" - "@typescript-eslint/visitor-keys" "6.1.0" + "@typescript-eslint/types" "6.4.0" + "@typescript-eslint/visitor-keys" "6.4.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/utils@6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.1.0.tgz#1641843792b4e3451cc692e2c73055df8b26f453" - integrity sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ== +"@typescript-eslint/utils@6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.4.0.tgz#23e996b693603c5924b1fbb733cc73196256baa5" + integrity sha512-BvvwryBQpECPGo8PwF/y/q+yacg8Hn/2XS+DqL/oRsOPK+RPt29h5Ui5dqOKHDlbXrAeHUTnyG3wZA0KTDxRZw== dependencies: "@eslint-community/eslint-utils" "^4.4.0" "@types/json-schema" "^7.0.12" "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.1.0" - "@typescript-eslint/types" "6.1.0" - "@typescript-eslint/typescript-estree" "6.1.0" + "@typescript-eslint/scope-manager" "6.4.0" + "@typescript-eslint/types" "6.4.0" + "@typescript-eslint/typescript-estree" "6.4.0" semver "^7.5.4" -"@typescript-eslint/visitor-keys@6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz#d2b84dff6b58944d3257ea03687e269a788c73be" - integrity sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A== +"@typescript-eslint/visitor-keys@6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.0.tgz#96a426cdb1add28274abd7a34aefe27f8b7d51ef" + integrity sha512-yJSfyT+uJm+JRDWYRYdCm2i+pmvXJSMtPR9Cq5/XQs4QIgNoLcoRtDdzsLbLsFM/c6um6ohQkg/MLxWvoIndJA== dependencies: - "@typescript-eslint/types" "6.1.0" + "@typescript-eslint/types" "6.4.0" eslint-visitor-keys "^3.4.1" acorn-jsx@^5.3.2: @@ -1197,7 +1222,7 @@ acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== -ajv@^6.10.0, ajv@^6.12.4: +ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1272,6 +1297,14 @@ aria-query@^5.1.3: dependencies: deep-equal "^2.0.5" +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + array-includes@^3.1.5, array-includes@^3.1.6: version "3.1.6" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" @@ -1288,6 +1321,17 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array.prototype.findlastindex@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz#bc229aef98f6bd0533a2bc61ff95209875526c9b" + integrity sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.1.3" + array.prototype.flat@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" @@ -1319,11 +1363,30 @@ array.prototype.tosorted@^1.1.1: es-shim-unscopables "^1.0.0" get-intrinsic "^1.1.3" +arraybuffer.prototype.slice@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz#9b5ea3868a6eebc30273da577eb888381c0044bb" + integrity sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= +asynciterator.prototype@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz#8c5df0514936cdd133604dfcc9d3fb93f09b2b62" + integrity sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg== + dependencies: + has-symbols "^1.0.3" + available-typed-arrays@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" @@ -1341,12 +1404,12 @@ axobject-query@^3.1.1: dependencies: deep-equal "^2.0.5" -babel-jest@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.6.1.tgz#a7141ad1ed5ec50238f3cd36127636823111233a" - integrity sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A== +babel-jest@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.6.2.tgz#cada0a59e07f5acaeb11cbae7e3ba92aec9c1126" + integrity sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A== dependencies: - "@jest/transform" "^29.6.1" + "@jest/transform" "^29.6.2" "@types/babel__core" "^7.1.14" babel-plugin-istanbul "^6.1.1" babel-preset-jest "^29.5.0" @@ -1493,7 +1556,7 @@ caniuse-lite@^1.0.30001503: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz#90fabae294215c3495807eb24fc809e11dc2f0a8" integrity sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA== -chalk@^2.0.0: +chalk@^2.0.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== @@ -1620,10 +1683,10 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: dependencies: ms "2.1.2" -dedent@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== +dedent@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" + integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== deep-equal@^2.0.5: version "2.2.0" @@ -1671,6 +1734,14 @@ define-properties@^1.1.3, define-properties@^1.1.4: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +define-properties@^1.2.0: + 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" + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -1817,6 +1888,51 @@ es-abstract@^1.20.4: string.prototype.trimstart "^1.0.5" unbox-primitive "^1.0.2" +es-abstract@^1.21.2, es-abstract@^1.21.3: + version "1.22.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc" + integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw== + dependencies: + array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.1" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.2.1" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.0" + safe-array-concat "^1.0.0" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.10" + es-get-iterator@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6" @@ -1832,6 +1948,31 @@ es-get-iterator@^1.1.2: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" +es-iterator-helpers@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.12.tgz#272f7270f270f4d63dd8aa718228ffa901fd086e" + integrity sha512-T6Ldv67RYULYtZ1k1omngDTVQSTVNX/ZSjDiwlw0PMokhy8kq2LFElleaEjpvlSaXh9ugJ4zrBgbQ7L+Bjdm3Q== + dependencies: + asynciterator.prototype "^1.0.0" + es-abstract "^1.21.3" + es-set-tostringtag "^2.0.1" + function-bind "^1.1.1" + globalthis "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + iterator.prototype "^1.1.0" + safe-array-concat "^1.0.0" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + es-shim-unscopables@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" @@ -1873,10 +2014,10 @@ eslint-config-fbjs@^4.0.0: resolved "https://registry.yarnpkg.com/eslint-config-fbjs/-/eslint-config-fbjs-4.0.0.tgz#9b2e70c57bca58ba4dfafe3a566bdb077146455f" integrity sha512-GKXvVfpgVgXdxzmYeaqiBJFL58o+T9d5J8EMXYy3AsyD3AtEdsHzwd+4bEqSI2A0RbeF27CAj9+o2v9VhWSLIg== -eslint-config-prettier@^8.8.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" - integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== +eslint-config-prettier@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz#eb25485946dd0c66cd216a46232dc05451518d1f" + integrity sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw== eslint-import-resolver-node@^0.3.7: version "0.3.7" @@ -1887,19 +2028,18 @@ eslint-import-resolver-node@^0.3.7: is-core-module "^2.11.0" resolve "^1.22.1" -eslint-import-resolver-typescript@^3.5.5: - version "3.5.5" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz#0a9034ae7ed94b254a360fbea89187b60ea7456d" - integrity sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw== +eslint-import-resolver-typescript@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.0.tgz#36f93e1eb65a635e688e16cae4bead54552e3bbd" + integrity sha512-QTHR9ddNnn35RTxlaEnx2gCxqFlF2SEN0SE2d17SqwyM7YOSI2GHWRYp5BiRkObTUNYPupC/3Fq2a0PpT+EKpg== dependencies: debug "^4.3.4" enhanced-resolve "^5.12.0" eslint-module-utils "^2.7.4" + fast-glob "^3.3.1" get-tsconfig "^4.5.0" - globby "^13.1.3" is-core-module "^2.11.0" is-glob "^4.0.3" - synckit "^0.8.5" eslint-module-utils@^2.7.4: version "2.7.4" @@ -1908,6 +2048,13 @@ eslint-module-utils@^2.7.4: dependencies: debug "^3.2.7" +eslint-module-utils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" + integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== + dependencies: + debug "^3.2.7" + eslint-plugin-babel@^5.3.0: version "5.3.1" resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.3.1.tgz#75a2413ffbf17e7be57458301c60291f2cfbf560" @@ -1923,10 +2070,10 @@ eslint-plugin-es@^3.0.0: eslint-utils "^2.0.0" regexpp "^3.0.0" -eslint-plugin-ft-flow@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-ft-flow/-/eslint-plugin-ft-flow-2.0.3.tgz#3b3c113c41902bcbacf0e22b536debcfc3c819e8" - integrity sha512-Vbsd/b+LYA99jUbsL6viEUWShFaYQt2YQs3QN3f+aeszOhh2sgdcU0mjzDyD4yyBvMc8qy2uwvBBWfMzEX06tg== +eslint-plugin-ft-flow@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-ft-flow/-/eslint-plugin-ft-flow-3.0.0.tgz#e9cbe4531089c2a85726928baa2d30d24d9af3b5" + integrity sha512-fz5ep5V2jh5aNBHoCKOdq+xxGenxYMfmOq8F6MUnFGyeEncJgV91O7mOWyKTZN0h/ofP+yW1CS7fZq8iEglNxw== dependencies: lodash "^4.17.21" string-natural-compare "^3.0.1" @@ -1936,26 +2083,29 @@ eslint-plugin-header@^3.0.0: resolved "https://registry.yarnpkg.com/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz#6ce512432d57675265fac47292b50d1eff11acd6" integrity sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg== -eslint-plugin-import@^2.27.5: - version "2.27.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" - integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== +eslint-plugin-import@^2.28.0: + version "2.28.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.0.tgz#8d66d6925117b06c4018d491ae84469eb3cb1005" + integrity sha512-B8s/n+ZluN7sxj9eUf7/pRFERX0r5bnFA2dCaLHy2ZeaQEAz0k+ZZkFWRFHJAqxfxQDx6KLv9LeIki7cFdwW+Q== dependencies: array-includes "^3.1.6" + array.prototype.findlastindex "^1.2.2" array.prototype.flat "^1.3.1" array.prototype.flatmap "^1.3.1" debug "^3.2.7" doctrine "^2.1.0" eslint-import-resolver-node "^0.3.7" - eslint-module-utils "^2.7.4" + eslint-module-utils "^2.8.0" has "^1.0.3" - is-core-module "^2.11.0" + is-core-module "^2.12.1" is-glob "^4.0.3" minimatch "^3.1.2" + object.fromentries "^2.0.6" + object.groupby "^1.0.0" object.values "^1.1.6" - resolve "^1.22.1" - semver "^6.3.0" - tsconfig-paths "^3.14.1" + resolve "^1.22.3" + semver "^6.3.1" + tsconfig-paths "^3.14.2" eslint-plugin-jsx-a11y@^6.7.1: version "6.7.1" @@ -2004,15 +2154,16 @@ eslint-plugin-react-hooks@^4.5.0: resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== -eslint-plugin-react@^7.33.0: - version "7.33.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.0.tgz#6c356fb0862fec2cd1b04426c669ea746e9b6eb3" - integrity sha512-qewL/8P34WkY8jAqdQxsiL82pDUeT7nhs8IsuXgfgnsEloKCT4miAV9N9kGtx7/KM9NH/NCGUE7Edt9iGxLXFw== +eslint-plugin-react@^7.33.2: + version "7.33.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz#69ee09443ffc583927eafe86ffebb470ee737608" + integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw== dependencies: array-includes "^3.1.6" array.prototype.flatmap "^1.3.1" array.prototype.tosorted "^1.1.1" doctrine "^2.1.0" + es-iterator-helpers "^1.0.12" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" @@ -2038,10 +2189,10 @@ eslint-scope@5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" - integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -2068,27 +2219,32 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== -eslint@8.45.0: - version "8.45.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.45.0.tgz#bab660f90d18e1364352c0a6b7c6db8edb458b78" - integrity sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw== +eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@8.47.0: + version "8.47.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.47.0.tgz#c95f9b935463fb4fad7005e626c7621052e90806" + integrity sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q== dependencies: "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.4.0" - "@eslint/eslintrc" "^2.1.0" - "@eslint/js" "8.44.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.2" + "@eslint/js" "^8.47.0" "@humanwhocodes/config-array" "^0.11.10" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" - ajv "^6.10.0" + ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.3.2" doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.2.0" - eslint-visitor-keys "^3.4.1" - espree "^9.6.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -2111,7 +2267,7 @@ eslint@8.45.0: strip-ansi "^6.0.1" text-table "^0.2.0" -espree@^9.6.0: +espree@^9.6.0, espree@^9.6.1: version "9.6.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== @@ -2185,17 +2341,17 @@ expect@^29.0.0: jest-message-util "^29.4.2" jest-util "^29.4.2" -expect@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.6.1.tgz#64dd1c8f75e2c0b209418f2b8d36a07921adfdf1" - integrity sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g== +expect@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.6.2.tgz#7b08e83eba18ddc4a2cf62b5f2d1918f5cd84521" + integrity sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA== dependencies: - "@jest/expect-utils" "^29.6.1" + "@jest/expect-utils" "^29.6.2" "@types/node" "*" jest-get-type "^29.4.3" - jest-matcher-utils "^29.6.1" - jest-message-util "^29.6.1" - jest-util "^29.6.1" + jest-matcher-utils "^29.6.2" + jest-message-util "^29.6.2" + jest-util "^29.6.2" fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" @@ -2207,7 +2363,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-glob@^3.2.11, fast-glob@^3.2.9: +fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== @@ -2218,6 +2374,17 @@ fast-glob@^3.2.11, fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" +fast-glob@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -2317,7 +2484,7 @@ function.prototype.name@^1.1.5: es-abstract "^1.19.0" functions-have-names "^1.2.2" -functions-have-names@^1.2.2: +functions-have-names@^1.2.2, functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== @@ -2341,6 +2508,16 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@ has "^1.0.3" has-symbols "^1.0.3" +get-intrinsic@^1.2.0, get-intrinsic@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + get-package-type@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" @@ -2402,6 +2579,13 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + globalyzer@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465" @@ -2419,17 +2603,6 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -globby@^13.1.3: - version "13.1.4" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.4.tgz#2f91c116066bcec152465ba36e5caa4a13c01317" - integrity sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g== - dependencies: - dir-glob "^3.0.1" - fast-glob "^3.2.11" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^4.0.0" - globrex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" @@ -2474,6 +2647,11 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" @@ -2565,6 +2743,15 @@ internal-slot@^1.0.4: has "^1.0.3" side-channel "^1.0.4" +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -2582,11 +2769,27 @@ is-array-buffer@^3.0.1: get-intrinsic "^1.1.3" is-typed-array "^1.1.10" +is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== +is-async-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== + dependencies: + has-tostringtag "^1.0.0" + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -2614,6 +2817,13 @@ is-core-module@^2.11.0: dependencies: has "^1.0.3" +is-core-module@^2.12.1, is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + dependencies: + has "^1.0.3" + is-core-module@^2.9.0: version "2.10.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" @@ -2638,6 +2848,13 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-finalizationregistry@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" + integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== + dependencies: + call-bind "^1.0.2" + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -2648,6 +2865,13 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-generator-function@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -2732,6 +2956,13 @@ is-typed-array@^1.1.10: gopd "^1.0.1" has-tostringtag "^1.0.0" +is-typed-array@^1.1.9: + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== + dependencies: + which-typed-array "^1.1.11" + is-weakmap@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" @@ -2816,6 +3047,17 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +iterator.prototype@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.0.tgz#690c88b043d821f783843aaf725d7ac3b62e3b46" + integrity sha512-rjuhAk1AJ1fssphHD0IFV6TWL40CwRZ53FrztKx43yk2v6rguBYsY4Bj1VU4HmoMmKwZUlx7mfnhDf9cOp4YTw== + dependencies: + define-properties "^1.1.4" + get-intrinsic "^1.1.3" + has-symbols "^1.0.3" + has-tostringtag "^1.0.0" + reflect.getprototypeof "^1.0.3" + jest-changed-files@^29.5.0: version "29.5.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.5.0.tgz#e88786dca8bf2aa899ec4af7644e16d9dcf9b23e" @@ -2824,75 +3066,75 @@ jest-changed-files@^29.5.0: execa "^5.0.0" p-limit "^3.1.0" -jest-circus@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.6.1.tgz#861dab37e71a89907d1c0fabc54a0019738ed824" - integrity sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ== +jest-circus@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.6.2.tgz#1e6ffca60151ac66cad63fce34f443f6b5bb4258" + integrity sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw== dependencies: - "@jest/environment" "^29.6.1" - "@jest/expect" "^29.6.1" - "@jest/test-result" "^29.6.1" + "@jest/environment" "^29.6.2" + "@jest/expect" "^29.6.2" + "@jest/test-result" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - dedent "^0.7.0" + dedent "^1.0.0" is-generator-fn "^2.0.0" - jest-each "^29.6.1" - jest-matcher-utils "^29.6.1" - jest-message-util "^29.6.1" - jest-runtime "^29.6.1" - jest-snapshot "^29.6.1" - jest-util "^29.6.1" + jest-each "^29.6.2" + jest-matcher-utils "^29.6.2" + jest-message-util "^29.6.2" + jest-runtime "^29.6.2" + jest-snapshot "^29.6.2" + jest-util "^29.6.2" p-limit "^3.1.0" - pretty-format "^29.6.1" + pretty-format "^29.6.2" pure-rand "^6.0.0" slash "^3.0.0" stack-utils "^2.0.3" -jest-cli@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.6.1.tgz#99d9afa7449538221c71f358f0fdd3e9c6e89f72" - integrity sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing== +jest-cli@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.6.2.tgz#edb381763398d1a292cd1b636a98bfa5644b8fda" + integrity sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q== dependencies: - "@jest/core" "^29.6.1" - "@jest/test-result" "^29.6.1" + "@jest/core" "^29.6.2" + "@jest/test-result" "^29.6.2" "@jest/types" "^29.6.1" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.9" import-local "^3.0.2" - jest-config "^29.6.1" - jest-util "^29.6.1" - jest-validate "^29.6.1" + jest-config "^29.6.2" + jest-util "^29.6.2" + jest-validate "^29.6.2" prompts "^2.0.1" yargs "^17.3.1" -jest-config@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.6.1.tgz#d785344509065d53a238224c6cdc0ed8e2f2f0dd" - integrity sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ== +jest-config@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.6.2.tgz#c68723f06b31ca5e63030686e604727d406cd7c3" + integrity sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw== dependencies: "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.6.1" + "@jest/test-sequencer" "^29.6.2" "@jest/types" "^29.6.1" - babel-jest "^29.6.1" + babel-jest "^29.6.2" chalk "^4.0.0" ci-info "^3.2.0" deepmerge "^4.2.2" glob "^7.1.3" graceful-fs "^4.2.9" - jest-circus "^29.6.1" - jest-environment-node "^29.6.1" + jest-circus "^29.6.2" + jest-environment-node "^29.6.2" jest-get-type "^29.4.3" jest-regex-util "^29.4.3" - jest-resolve "^29.6.1" - jest-runner "^29.6.1" - jest-util "^29.6.1" - jest-validate "^29.6.1" + jest-resolve "^29.6.2" + jest-runner "^29.6.2" + jest-util "^29.6.2" + jest-validate "^29.6.2" micromatch "^4.0.4" parse-json "^5.2.0" - pretty-format "^29.6.1" + pretty-format "^29.6.2" slash "^3.0.0" strip-json-comments "^3.1.1" @@ -2906,15 +3148,15 @@ jest-diff@^29.4.2: jest-get-type "^29.4.2" pretty-format "^29.4.2" -jest-diff@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.6.1.tgz#13df6db0a89ee6ad93c747c75c85c70ba941e545" - integrity sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg== +jest-diff@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.6.2.tgz#c36001e5543e82a0805051d3ceac32e6825c1c46" + integrity sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA== dependencies: chalk "^4.0.0" diff-sequences "^29.4.3" jest-get-type "^29.4.3" - pretty-format "^29.6.1" + pretty-format "^29.6.2" jest-docblock@^29.4.3: version "29.4.3" @@ -2923,28 +3165,28 @@ jest-docblock@^29.4.3: dependencies: detect-newline "^3.0.0" -jest-each@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.6.1.tgz#975058e5b8f55c6780beab8b6ab214921815c89c" - integrity sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ== +jest-each@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.6.2.tgz#c9e4b340bcbe838c73adf46b76817b15712d02ce" + integrity sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw== dependencies: "@jest/types" "^29.6.1" chalk "^4.0.0" jest-get-type "^29.4.3" - jest-util "^29.6.1" - pretty-format "^29.6.1" + jest-util "^29.6.2" + pretty-format "^29.6.2" -jest-environment-node@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.6.1.tgz#08a122dece39e58bc388da815a2166c58b4abec6" - integrity sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ== +jest-environment-node@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.6.2.tgz#a9ea2cabff39b08eca14ccb32c8ceb924c8bb1ad" + integrity sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ== dependencies: - "@jest/environment" "^29.6.1" - "@jest/fake-timers" "^29.6.1" + "@jest/environment" "^29.6.2" + "@jest/fake-timers" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" - jest-mock "^29.6.1" - jest-util "^29.6.1" + jest-mock "^29.6.2" + jest-util "^29.6.2" jest-get-type@^29.4.2: version "29.4.2" @@ -2956,10 +3198,10 @@ jest-get-type@^29.4.3: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5" integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg== -jest-haste-map@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.6.1.tgz#62655c7a1c1b349a3206441330fb2dbdb4b63803" - integrity sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig== +jest-haste-map@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.6.2.tgz#298c25ea5255cfad8b723179d4295cf3a50a70d1" + integrity sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA== dependencies: "@jest/types" "^29.6.1" "@types/graceful-fs" "^4.1.3" @@ -2968,20 +3210,20 @@ jest-haste-map@^29.6.1: fb-watchman "^2.0.0" graceful-fs "^4.2.9" jest-regex-util "^29.4.3" - jest-util "^29.6.1" - jest-worker "^29.6.1" + jest-util "^29.6.2" + jest-worker "^29.6.2" micromatch "^4.0.4" walker "^1.0.8" optionalDependencies: fsevents "^2.3.2" -jest-leak-detector@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz#66a902c81318e66e694df7d096a95466cb962f8e" - integrity sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ== +jest-leak-detector@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz#e2b307fee78cab091c37858a98c7e1d73cdf5b38" + integrity sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ== dependencies: jest-get-type "^29.4.3" - pretty-format "^29.6.1" + pretty-format "^29.6.2" jest-matcher-utils@^29.4.2: version "29.4.2" @@ -2993,15 +3235,15 @@ jest-matcher-utils@^29.4.2: jest-get-type "^29.4.2" pretty-format "^29.4.2" -jest-matcher-utils@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz#6c60075d84655d6300c5d5128f46531848160b53" - integrity sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA== +jest-matcher-utils@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz#39de0be2baca7a64eacb27291f0bd834fea3a535" + integrity sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ== dependencies: chalk "^4.0.0" - jest-diff "^29.6.1" + jest-diff "^29.6.2" jest-get-type "^29.4.3" - pretty-format "^29.6.1" + pretty-format "^29.6.2" jest-message-util@^29.4.2: version "29.4.2" @@ -3018,10 +3260,10 @@ jest-message-util@^29.4.2: slash "^3.0.0" stack-utils "^2.0.3" -jest-message-util@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.6.1.tgz#d0b21d87f117e1b9e165e24f245befd2ff34ff8d" - integrity sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ== +jest-message-util@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.6.2.tgz#af7adc2209c552f3f5ae31e77cf0a261f23dc2bb" + integrity sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ== dependencies: "@babel/code-frame" "^7.12.13" "@jest/types" "^29.6.1" @@ -3029,18 +3271,18 @@ jest-message-util@^29.6.1: chalk "^4.0.0" graceful-fs "^4.2.9" micromatch "^4.0.4" - pretty-format "^29.6.1" + pretty-format "^29.6.2" slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.6.1.tgz#049ee26aea8cbf54c764af649070910607316517" - integrity sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw== +jest-mock@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.6.2.tgz#ef9c9b4d38c34a2ad61010a021866dad41ce5e00" + integrity sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg== dependencies: "@jest/types" "^29.6.1" "@types/node" "*" - jest-util "^29.6.1" + jest-util "^29.6.2" jest-pnp-resolver@^1.2.2: version "1.2.2" @@ -3052,67 +3294,67 @@ jest-regex-util@^29.4.3: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.4.3.tgz#a42616141e0cae052cfa32c169945d00c0aa0bb8" integrity sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg== -jest-resolve-dependencies@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz#b85b06670f987a62515bbf625d54a499e3d708f5" - integrity sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw== +jest-resolve-dependencies@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz#36435269b6672c256bcc85fb384872c134cc4cf2" + integrity sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w== dependencies: jest-regex-util "^29.4.3" - jest-snapshot "^29.6.1" + jest-snapshot "^29.6.2" -jest-resolve@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.6.1.tgz#4c3324b993a85e300add2f8609f51b80ddea39ee" - integrity sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg== +jest-resolve@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.6.2.tgz#f18405fe4b50159b7b6d85e81f6a524d22afb838" + integrity sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw== dependencies: chalk "^4.0.0" graceful-fs "^4.2.9" - jest-haste-map "^29.6.1" + jest-haste-map "^29.6.2" jest-pnp-resolver "^1.2.2" - jest-util "^29.6.1" - jest-validate "^29.6.1" + jest-util "^29.6.2" + jest-validate "^29.6.2" resolve "^1.20.0" resolve.exports "^2.0.0" slash "^3.0.0" -jest-runner@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.6.1.tgz#54557087e7972d345540d622ab5bfc3d8f34688c" - integrity sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ== +jest-runner@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.6.2.tgz#89e8e32a8fef24781a7c4c49cd1cb6358ac7fc01" + integrity sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w== dependencies: - "@jest/console" "^29.6.1" - "@jest/environment" "^29.6.1" - "@jest/test-result" "^29.6.1" - "@jest/transform" "^29.6.1" + "@jest/console" "^29.6.2" + "@jest/environment" "^29.6.2" + "@jest/test-result" "^29.6.2" + "@jest/transform" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" chalk "^4.0.0" emittery "^0.13.1" graceful-fs "^4.2.9" jest-docblock "^29.4.3" - jest-environment-node "^29.6.1" - jest-haste-map "^29.6.1" - jest-leak-detector "^29.6.1" - jest-message-util "^29.6.1" - jest-resolve "^29.6.1" - jest-runtime "^29.6.1" - jest-util "^29.6.1" - jest-watcher "^29.6.1" - jest-worker "^29.6.1" + jest-environment-node "^29.6.2" + jest-haste-map "^29.6.2" + jest-leak-detector "^29.6.2" + jest-message-util "^29.6.2" + jest-resolve "^29.6.2" + jest-runtime "^29.6.2" + jest-util "^29.6.2" + jest-watcher "^29.6.2" + jest-worker "^29.6.2" p-limit "^3.1.0" source-map-support "0.5.13" -jest-runtime@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.6.1.tgz#8a0fc9274ef277f3d70ba19d238e64334958a0dc" - integrity sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ== +jest-runtime@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.6.2.tgz#692f25e387f982e89ab83270e684a9786248e545" + integrity sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg== dependencies: - "@jest/environment" "^29.6.1" - "@jest/fake-timers" "^29.6.1" - "@jest/globals" "^29.6.1" + "@jest/environment" "^29.6.2" + "@jest/fake-timers" "^29.6.2" + "@jest/globals" "^29.6.2" "@jest/source-map" "^29.6.0" - "@jest/test-result" "^29.6.1" - "@jest/transform" "^29.6.1" + "@jest/test-result" "^29.6.2" + "@jest/transform" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" chalk "^4.0.0" @@ -3120,41 +3362,40 @@ jest-runtime@^29.6.1: collect-v8-coverage "^1.0.0" glob "^7.1.3" graceful-fs "^4.2.9" - jest-haste-map "^29.6.1" - jest-message-util "^29.6.1" - jest-mock "^29.6.1" + jest-haste-map "^29.6.2" + jest-message-util "^29.6.2" + jest-mock "^29.6.2" jest-regex-util "^29.4.3" - jest-resolve "^29.6.1" - jest-snapshot "^29.6.1" - jest-util "^29.6.1" + jest-resolve "^29.6.2" + jest-snapshot "^29.6.2" + jest-util "^29.6.2" slash "^3.0.0" strip-bom "^4.0.0" -jest-snapshot@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.6.1.tgz#0d083cb7de716d5d5cdbe80d598ed2fbafac0239" - integrity sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A== +jest-snapshot@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.6.2.tgz#9b431b561a83f2bdfe041e1cab8a6becdb01af9c" + integrity sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA== dependencies: "@babel/core" "^7.11.6" "@babel/generator" "^7.7.2" "@babel/plugin-syntax-jsx" "^7.7.2" "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.6.1" - "@jest/transform" "^29.6.1" + "@jest/expect-utils" "^29.6.2" + "@jest/transform" "^29.6.2" "@jest/types" "^29.6.1" - "@types/prettier" "^2.1.5" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^29.6.1" + expect "^29.6.2" graceful-fs "^4.2.9" - jest-diff "^29.6.1" + jest-diff "^29.6.2" jest-get-type "^29.4.3" - jest-matcher-utils "^29.6.1" - jest-message-util "^29.6.1" - jest-util "^29.6.1" + jest-matcher-utils "^29.6.2" + jest-message-util "^29.6.2" + jest-util "^29.6.2" natural-compare "^1.4.0" - pretty-format "^29.6.1" + pretty-format "^29.6.2" semver "^7.5.3" jest-util@^29.0.0, jest-util@^29.4.2: @@ -3169,10 +3410,10 @@ jest-util@^29.0.0, jest-util@^29.4.2: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-util@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.6.1.tgz#c9e29a87a6edbf1e39e6dee2b4689b8a146679cb" - integrity sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg== +jest-util@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.6.2.tgz#8a052df8fff2eebe446769fd88814521a517664d" + integrity sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w== dependencies: "@jest/types" "^29.6.1" "@types/node" "*" @@ -3181,51 +3422,51 @@ jest-util@^29.6.1: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-validate@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.6.1.tgz#765e684af6e2c86dce950aebefbbcd4546d69f7b" - integrity sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA== +jest-validate@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.6.2.tgz#25d972af35b2415b83b1373baf1a47bb266c1082" + integrity sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg== dependencies: "@jest/types" "^29.6.1" camelcase "^6.2.0" chalk "^4.0.0" jest-get-type "^29.4.3" leven "^3.1.0" - pretty-format "^29.6.1" + pretty-format "^29.6.2" -jest-watcher@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.6.1.tgz#7c0c43ddd52418af134c551c92c9ea31e5ec942e" - integrity sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA== +jest-watcher@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.6.2.tgz#77c224674f0620d9f6643c4cfca186d8893ca088" + integrity sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA== dependencies: - "@jest/test-result" "^29.6.1" + "@jest/test-result" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" emittery "^0.13.1" - jest-util "^29.6.1" + jest-util "^29.6.2" string-length "^4.0.1" -jest-worker@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.1.tgz#64b015f0e985ef3a8ad049b61fe92b3db74a5319" - integrity sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA== +jest-worker@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.2.tgz#682fbc4b6856ad0aa122a5403c6d048b83f3fb44" + integrity sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ== dependencies: "@types/node" "*" - jest-util "^29.6.1" + jest-util "^29.6.2" merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.6.1.tgz#74be1cb719c3abe439f2d94aeb18e6540a5b02ad" - integrity sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw== +jest@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.6.2.tgz#3bd55b9fd46a161b2edbdf5f1d1bd0d1eab76c42" + integrity sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg== dependencies: - "@jest/core" "^29.6.1" + "@jest/core" "^29.6.2" "@jest/types" "^29.6.1" import-local "^3.0.2" - jest-cli "^29.6.1" + jest-cli "^29.6.2" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" @@ -3267,10 +3508,10 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" @@ -3451,11 +3692,6 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -natural-compare-lite@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" - integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -3509,6 +3745,11 @@ object-inspect@^1.12.2, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +object-inspect@^1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + object-is@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" @@ -3550,6 +3791,16 @@ object.fromentries@^2.0.6: define-properties "^1.1.4" es-abstract "^1.20.4" +object.groupby@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.0.tgz#cb29259cf90f37e7bac6437686c1ea8c916d12a9" + integrity sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.21.2" + get-intrinsic "^1.2.1" + object.hasown@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92" @@ -3718,10 +3969,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.0.tgz#e7b19f691245a21d618c68bc54dc06122f6105ae" - integrity sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g== +prettier@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.2.tgz#78fcecd6d870551aa5547437cdae39d4701dca5b" + integrity sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ== pretty-format@^29.0.0, pretty-format@^29.4.2: version "29.4.2" @@ -3732,10 +3983,10 @@ pretty-format@^29.0.0, pretty-format@^29.4.2: ansi-styles "^5.0.0" react-is "^18.0.0" -pretty-format@^29.6.1: - version "29.6.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.6.1.tgz#ec838c288850b7c4f9090b867c2d4f4edbfb0f3e" - integrity sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog== +pretty-format@^29.6.2: + version "29.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.6.2.tgz#3d5829261a8a4d89d8b9769064b29c50ed486a47" + integrity sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg== dependencies: "@jest/schemas" "^29.6.0" ansi-styles "^5.0.0" @@ -3783,6 +4034,18 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +reflect.getprototypeof@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.3.tgz#2738fd896fcc3477ffbd4190b40c2458026b6928" + integrity sha512-TTAOZpkJ2YLxl7mVHWrNo3iDMEkYlva/kgFcXndqMgbo/AZUmmavEkdXV+hXtE4P8xdyEKRzalaFqZVuwIk/Nw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + get-intrinsic "^1.1.1" + globalthis "^1.0.3" + which-builtin-type "^1.1.3" + regenerator-runtime@^0.13.11: version "0.13.11" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" @@ -3797,6 +4060,15 @@ regexp.prototype.flags@^1.4.3: define-properties "^1.1.3" functions-have-names "^1.2.2" +regexp.prototype.flags@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + functions-have-names "^1.2.3" + regexpp@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" @@ -3838,6 +4110,15 @@ resolve@^1.10.1, resolve@^1.20.0, resolve@^1.22.1: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^1.22.3: + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^2.0.0-next.4: version "2.0.0-next.4" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" @@ -3866,6 +4147,16 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +safe-array-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" + integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + has-symbols "^1.0.3" + isarray "^2.0.5" + safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -3952,11 +4243,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -4025,6 +4311,15 @@ string.prototype.matchall@^4.0.8: regexp.prototype.flags "^1.4.3" side-channel "^1.0.4" +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimend@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" @@ -4034,6 +4329,15 @@ string.prototype.trimend@^1.0.5: define-properties "^1.1.4" es-abstract "^1.19.5" +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + string.prototype.trimstart@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" @@ -4043,6 +4347,15 @@ string.prototype.trimstart@^1.0.5: define-properties "^1.1.4" es-abstract "^1.19.5" +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -4167,13 +4480,13 @@ ts-jest@^29.1.0: semver "^7.5.3" yargs-parser "^21.0.1" -tsconfig-paths@^3.14.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" - integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== +tsconfig-paths@^3.14.2: + version "3.14.2" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" + integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== dependencies: "@types/json5" "^0.0.29" - json5 "^1.0.1" + json5 "^1.0.2" minimist "^1.2.6" strip-bom "^3.0.0" @@ -4209,6 +4522,45 @@ 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== +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typescript@^5.1.6: version "5.1.6" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" @@ -4274,6 +4626,24 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-builtin-type@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" + integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== + dependencies: + function.prototype.name "^1.1.5" + has-tostringtag "^1.0.0" + is-async-function "^2.0.0" + is-date-object "^1.0.5" + is-finalizationregistry "^1.0.2" + is-generator-function "^1.0.10" + is-regex "^1.1.4" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.9" + which-collection@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" @@ -4284,6 +4654,17 @@ which-collection@^1.0.1: is-weakmap "^2.0.1" is-weakset "^2.0.1" +which-typed-array@^1.1.10, which-typed-array@^1.1.11: + version "1.1.11" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" + integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + which-typed-array@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" diff --git a/packer/Cargo.lock b/packer/Cargo.lock index 5e152961ed4..f43c4bf5547 100644 --- a/packer/Cargo.lock +++ b/packer/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.18" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.72" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "8c6f84b74db2535ebae81eede2f39b947dcbf01d093ae5f791e5dd414a1bf289" [[package]] name = "atty" @@ -23,7 +23,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -42,18 +42,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "bstr" -version = "1.1.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", "serde", @@ -61,9 +61,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.73" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -73,16 +76,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.1.17" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47582c09be7c8b32c0ab3a6181825ababb713fde6fff20fc573a3870dd45c6a0" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", "bitflags", "clap_derive", "clap_lex", - "indexmap 1.9.1", - "lazy_static", + "indexmap 1.9.3", + "once_cell", "strsim", "termcolor", "textwrap", @@ -90,55 +93,53 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.1.7" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ "heck", "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] name = "clap_lex" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", ] [[package]] name = "console" -version = "0.15.0" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" dependencies = [ "encode_unicode", + "lazy_static", "libc", - "once_cell", - "regex", - "terminal_size", "unicode-width", - "winapi", + "windows-sys 0.45.0", ] [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if", "crossbeam-utils", @@ -146,9 +147,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -157,33 +158,31 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "lazy_static", "memoffset", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", - "lazy_static", ] [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", @@ -207,29 +206,30 @@ dependencies = [ [[package]] name = "dirs" -version = "4.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.7" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", + "option-ext", "redox_users", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "either" -version = "1.6.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "encode_unicode" @@ -245,14 +245,14 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "filetime" -version = "0.2.15" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if", "libc", - "redox_syscall", - "winapi", + "redox_syscall 0.3.5", + "windows-sys 0.48.0", ] [[package]] @@ -289,9 +289,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -299,9 +299,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -310,9 +310,9 @@ dependencies = [ [[package]] name = "globset" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" dependencies = [ "aho-corasick", "bstr", @@ -335,9 +335,9 @@ checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -348,6 +348,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + [[package]] name = "ignore" version = "0.4.20" @@ -367,9 +373,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", @@ -387,9 +393,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.5" +version = "0.17.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff8cc23a7393a397ed1d7f56e6365cba772aba9f9912ab968b03043c395d057" +checksum = "0b297dc40733f23a0e52728a58fa9489a5b7638a324932de16b41adc3ef80730" dependencies = [ "console", "instant", @@ -409,9 +415,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "lazy_static" @@ -421,24 +427,21 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.121" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "log" -version = "0.4.16" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lzma-sys" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e06754c4acf47d49c727d5665ca9fb828851cda315ed3bd51edd148ef78a8772" +checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" dependencies = [ "cc", "libc", @@ -447,26 +450,26 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.6.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.2", "libc", ] @@ -478,27 +481,33 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "once_cell" -version = "1.10.0" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "os_str_bytes" -version = "6.0.0" +version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "portable-atomic" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc59d1bcc64fc5d021d67521f818db868368028108d37f0e98d74e33f68297b5" +checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e" [[package]] name = "proc-macro-error" @@ -509,7 +518,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", "version_check", ] @@ -526,18 +535,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.29" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -603,9 +612,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] @@ -617,15 +635,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", - "redox_syscall", + "redox_syscall 0.2.16", "thiserror", ] [[package]] name = "regex" -version = "1.5.5" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" dependencies = [ "aho-corasick", "memchr", @@ -634,9 +664,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "remove_dir_all" @@ -649,9 +679,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -664,35 +694,35 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.175" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.175" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", - "syn 2.0.26", + "syn 2.0.28", ] [[package]] name = "serde_json" -version = "1.0.80" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f972498cf015f7c0746cac89ebe1d6ef10c293b94175a243a2d9442c163d9944" +checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" dependencies = [ "itoa", "ryu", @@ -740,9 +770,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.104" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -751,9 +781,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.26" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -762,9 +792,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.39" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96d2ffad078296368d46ff1cb309be1c23c513b4ab0e22a45de0185275ac96" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ "filetime", "libc", @@ -783,69 +813,60 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] -[[package]] -name = "terminal_size" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "textwrap" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "d9207952ae1a003f42d3d5e892dac3c6ba42aa6ac0c79a6a91a2b5cb4253e75c" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "f1728216d3244de4f14f14f8c15c79be1a7c67867d28d69b719690e2a19fb445" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 2.0.28", ] [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if", "once_cell", ] [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-width" @@ -855,9 +876,9 @@ checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unsafe-libyaml" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad2024452afd3874bf539695e04af6732ba06517424dbf958fdb16a01f3bef6c" +checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" [[package]] name = "version_check" @@ -867,20 +888,19 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" dependencies = [ "same-file", - "winapi", "winapi-util", ] [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "winapi" @@ -913,11 +933,143 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.2", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1eeca1c172a285ee6c2c84c341ccea837e7c01b12fbb2d0fe3c9e550ce49ec8" +dependencies = [ + "windows_aarch64_gnullvm 0.48.2", + "windows_aarch64_msvc 0.48.2", + "windows_i686_gnu 0.48.2", + "windows_i686_msvc 0.48.2", + "windows_x86_64_gnu 0.48.2", + "windows_x86_64_gnullvm 0.48.2", + "windows_x86_64_msvc 0.48.2", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b10d0c968ba7f6166195e13d593af609ec2e3d24f916f081690695cf5eaffb2f" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "571d8d4e62f26d4932099a9efe89660e8bd5087775a2ab5cdd8b747b811f1058" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2229ad223e178db5fbbc8bd8d3835e51e566b8474bfca58d2e6150c48bb723cd" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "600956e2d840c194eedfc5d18f8242bc2e17c7775b6684488af3a9fff6fe3287" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea99ff3f8b49fb7a8e0d305e5aec485bd068c2ba691b6e277d29eaeac945868a" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1a05a1ece9a7a0d5a7ccf30ba2c33e3a61a30e042ffd247567d1de1d94120d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d419259aba16b663966e29e6d7c6ecfa0bb8425818bb96f6f1f3c3eb71a6e7b9" + [[package]] name = "xattr" -version = "0.2.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" dependencies = [ "libc", ] diff --git a/react-native/ReactNativeFlipperExample/android/app/src/debug/java/com/reactnativeflipperexample/ReactNativeFlipper.java b/react-native/ReactNativeFlipperExample/android/app/src/debug/java/com/reactnativeflipperexample/ReactNativeFlipper.java index d030fa7c10c..28ee0db7203 100644 --- a/react-native/ReactNativeFlipperExample/android/app/src/debug/java/com/reactnativeflipperexample/ReactNativeFlipper.java +++ b/react-native/ReactNativeFlipperExample/android/app/src/debug/java/com/reactnativeflipperexample/ReactNativeFlipper.java @@ -22,6 +22,7 @@ import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; import com.facebook.react.ReactInstanceManager; import com.facebook.react.bridge.ReactContext; +import com.facebook.react.modules.network.CustomClientBuilder; import com.facebook.react.modules.network.NetworkingModule; import okhttp3.OkHttpClient; @@ -38,7 +39,7 @@ public static void initializeFlipper(Context context, ReactInstanceManager react NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); NetworkingModule.setCustomClientBuilder( - new NetworkingModule.CustomClientBuilder() { + new CustomClientBuilder() { @Override public void apply(OkHttpClient.Builder builder) { builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); diff --git a/react-native/ReactNativeFlipperExample/ios/Podfile b/react-native/ReactNativeFlipperExample/ios/Podfile index f3583474f62..e630ed2176c 100644 --- a/react-native/ReactNativeFlipperExample/ios/Podfile +++ b/react-native/ReactNativeFlipperExample/ios/Podfile @@ -5,7 +5,7 @@ source 'https://github.com/CocoaPods/Specs' platform :ios, '12.4' # used for automatic bumping -flipperkit_version = '0.210.0' +flipperkit_version = '0.212.0' target 'ReactNativeFlipperExample' do config = use_native_modules! diff --git a/react-native/ReactNativeFlipperExample/ios/Podfile.lock b/react-native/ReactNativeFlipperExample/ios/Podfile.lock index c6b29d2f566..7a543fe4564 100644 --- a/react-native/ReactNativeFlipperExample/ios/Podfile.lock +++ b/react-native/ReactNativeFlipperExample/ios/Podfile.lock @@ -10,7 +10,7 @@ PODS: - React-Core (= 0.69.7) - React-jsi (= 0.69.7) - ReactCommon/turbomodule/core (= 0.69.7) - - Flipper (0.210.0): + - Flipper (0.212.0): - Flipper-Folly (~> 2.6) - Flipper-Boost-iOSX (1.76.0.1.11) - Flipper-DoubleConversion (3.2.0) @@ -26,46 +26,46 @@ PODS: - Flipper-PeerTalk (0.0.4) - Flipper-RSocket (1.4.3): - Flipper-Folly (~> 2.6) - - FlipperKit (0.210.0): - - FlipperKit/Core (= 0.210.0) - - FlipperKit/Core (0.210.0): - - Flipper (~> 0.210.0) + - FlipperKit (0.212.0): + - FlipperKit/Core (= 0.212.0) + - FlipperKit/Core (0.212.0): + - Flipper (~> 0.212.0) - FlipperKit/CppBridge - FlipperKit/FBCxxFollyDynamicConvert - FlipperKit/FBDefines - FlipperKit/FKPortForwarding - SocketRocket (~> 0.7.0) - - FlipperKit/CppBridge (0.210.0): - - Flipper (~> 0.210.0) - - FlipperKit/FBCxxFollyDynamicConvert (0.210.0): + - FlipperKit/CppBridge (0.212.0): + - Flipper (~> 0.212.0) + - FlipperKit/FBCxxFollyDynamicConvert (0.212.0): - Flipper-Folly (~> 2.6) - - FlipperKit/FBDefines (0.210.0) - - FlipperKit/FKPortForwarding (0.210.0): + - FlipperKit/FBDefines (0.212.0) + - FlipperKit/FKPortForwarding (0.212.0): - CocoaAsyncSocket (~> 7.6) - Flipper-PeerTalk (~> 0.0.4) - - FlipperKit/FlipperKitHighlightOverlay (0.210.0) - - FlipperKit/FlipperKitLayoutHelpers (0.210.0): + - FlipperKit/FlipperKitHighlightOverlay (0.212.0) + - FlipperKit/FlipperKitLayoutHelpers (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutTextSearchable - - FlipperKit/FlipperKitLayoutIOSDescriptors (0.210.0): + - FlipperKit/FlipperKitLayoutIOSDescriptors (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutHelpers - - FlipperKit/FlipperKitLayoutPlugin (0.210.0): + - FlipperKit/FlipperKitLayoutPlugin (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutHelpers - FlipperKit/FlipperKitLayoutIOSDescriptors - FlipperKit/FlipperKitLayoutTextSearchable - - FlipperKit/FlipperKitLayoutTextSearchable (0.210.0) - - FlipperKit/FlipperKitNetworkPlugin (0.210.0): + - FlipperKit/FlipperKitLayoutTextSearchable (0.212.0) + - FlipperKit/FlipperKitNetworkPlugin (0.212.0): - FlipperKit/Core - - FlipperKit/FlipperKitReactPlugin (0.210.0): + - FlipperKit/FlipperKitReactPlugin (0.212.0): - FlipperKit/Core - - FlipperKit/FlipperKitUserDefaultsPlugin (0.210.0): + - FlipperKit/FlipperKitUserDefaultsPlugin (0.212.0): - FlipperKit/Core - - FlipperKit/SKIOSNetworkPlugin (0.210.0): + - FlipperKit/SKIOSNetworkPlugin (0.212.0): - FlipperKit/Core - FlipperKit/FlipperKitNetworkPlugin - fmt (6.2.1) @@ -375,7 +375,7 @@ DEPENDENCIES: - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) - - Flipper (= 0.210.0) + - Flipper (= 0.212.0) - Flipper-Boost-iOSX (= 1.76.0.1.11) - Flipper-DoubleConversion (= 3.2.0) - Flipper-Fmt (= 7.1.7) @@ -383,19 +383,19 @@ DEPENDENCIES: - Flipper-Glog (= 0.5.0.3) - Flipper-PeerTalk (= 0.0.4) - Flipper-RSocket (= 1.4.3) - - FlipperKit (= 0.210.0) - - FlipperKit/Core (= 0.210.0) - - FlipperKit/CppBridge (= 0.210.0) - - FlipperKit/FBCxxFollyDynamicConvert (= 0.210.0) - - FlipperKit/FBDefines (= 0.210.0) - - FlipperKit/FKPortForwarding (= 0.210.0) - - FlipperKit/FlipperKitHighlightOverlay (= 0.210.0) - - FlipperKit/FlipperKitLayoutPlugin (= 0.210.0) - - FlipperKit/FlipperKitLayoutTextSearchable (= 0.210.0) - - FlipperKit/FlipperKitNetworkPlugin (= 0.210.0) - - FlipperKit/FlipperKitReactPlugin (= 0.210.0) - - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.210.0) - - FlipperKit/SKIOSNetworkPlugin (= 0.210.0) + - FlipperKit (= 0.212.0) + - FlipperKit/Core (= 0.212.0) + - FlipperKit/CppBridge (= 0.212.0) + - FlipperKit/FBCxxFollyDynamicConvert (= 0.212.0) + - FlipperKit/FBDefines (= 0.212.0) + - FlipperKit/FKPortForwarding (= 0.212.0) + - FlipperKit/FlipperKitHighlightOverlay (= 0.212.0) + - FlipperKit/FlipperKitLayoutPlugin (= 0.212.0) + - FlipperKit/FlipperKitLayoutTextSearchable (= 0.212.0) + - FlipperKit/FlipperKitNetworkPlugin (= 0.212.0) + - FlipperKit/FlipperKitReactPlugin (= 0.212.0) + - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.212.0) + - FlipperKit/SKIOSNetworkPlugin (= 0.212.0) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes/hermes-engine.podspec`) - libevent (~> 2.1.12) @@ -527,7 +527,7 @@ SPEC CHECKSUMS: DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: 6b7f5692909b4300d50e7359cdefbcd09dd30faa FBReactNativeSpec: affcf71d996f6b0c01f68883482588297b9d5e6e - Flipper: 4a5b2c2c6ac926d6881ead86c1b5411fc79da46e + Flipper: b7a3d90634c855fece9d491ca69f682f1244984f Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 3d3d04a078d4f3a1b6c6916587f159dc11f232c4 Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b @@ -535,7 +535,7 @@ SPEC CHECKSUMS: Flipper-Glog: 7761f5362d23ead28c19afc2dd1d819f00e40df9 Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541 - FlipperKit: c2aabe903823302c655ebbc33e1cc59d275fdcaa + FlipperKit: 73b2e0c1ed75801151dab992313b6b1951b67446 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 3d02b25ca00c2d456734d0bcff864cbc62f6ae1a hermes-engine: 51aaceb1f6dc1aed44b8bbf866f52ec146c00a89 @@ -572,6 +572,6 @@ SPEC CHECKSUMS: SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d Yoga: 0b84a956f7393ef1f37f3bb213c516184e4a689d -PODFILE CHECKSUM: 0380499299dd3960bad2a88e0e7bbb01418fcf95 +PODFILE CHECKSUM: 57d44f577e4f420511a2427799645b075948962c COCOAPODS: 1.12.1 diff --git a/react-native/react-native-flipper/package.json b/react-native/react-native-flipper/package.json index f9daa596359..e8b8c2b5206 100644 --- a/react-native/react-native-flipper/package.json +++ b/react-native/react-native-flipper/package.json @@ -1,7 +1,7 @@ { "name": "react-native-flipper", "title": "React Native Flipper Bindings", - "version": "0.210.1", + "version": "0.212.0", "description": "Flipper bindings for React Native", "main": "index.js", "types": "index.d.ts", diff --git a/xplat/Flipper/FlipperClient.cpp b/xplat/Flipper/FlipperClient.cpp index 345de0e199a..a317657461a 100644 --- a/xplat/Flipper/FlipperClient.cpp +++ b/xplat/Flipper/FlipperClient.cpp @@ -59,15 +59,17 @@ void FlipperClient::addPlugin(std::shared_ptr plugin) { performAndReportError([this, plugin]() { log("FlipperClient::addPlugin " + plugin->identifier()); auto step = flipperState_->start("Add plugin " + plugin->identifier()); + auto needs_refresh = false; std::lock_guard lock(mutex_); if (plugins_.find(plugin->identifier()) != plugins_.end()) { - throw std::out_of_range( - "plugin " + plugin->identifier() + " already added."); + log("plugin " + plugin->identifier() + " already added."); + } else { + plugins_[plugin->identifier()] = plugin; + needs_refresh = true; } - plugins_[plugin->identifier()] = plugin; step->complete(); - if (connected_) { + if (connected_ && needs_refresh) { refreshPlugins(); } }); @@ -90,7 +92,8 @@ void FlipperClient::removePlugin(std::shared_ptr plugin) { std::lock_guard lock(mutex_); if (plugins_.find(plugin->identifier()) == plugins_.end()) { - throw std::out_of_range("plugin " + plugin->identifier() + " not added."); + log("plugin " + plugin->identifier() + " not added."); + return; } disconnect(plugin); plugins_.erase(plugin->identifier());