/** * 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 type {ReactElement} from 'react'; import {Logger} from '../utils/Logger'; import {Device} from './DevicePlugin'; import {NormalizedMenuEntry} from './MenuEntry'; import {RealFlipperClient} from './Plugin'; import {Notification} from './Notification'; import { ExecOptions, ExecOut, BufferEncoding, MkdirOptions, DownloadFileStartOptions, DownloadFileStartResponse, DownloadFileUpdate, RmOptions, fsConstants, EnvironmentInfo, FSStatsLike, FlipperServerCommands, ENVIRONMENT_VARIABLES, User, } from 'flipper-common'; import {CreatePasteArgs, CreatePasteResult} from './Paste'; import {Atom} from '../state/atom'; export type FileEncoding = 'utf-8' | 'base64' | 'binary'; export interface FileDescriptor { data: string | Uint8Array | undefined; name: string; encoding: FileEncoding; } export interface DownloadFileResponse extends DownloadFileStartResponse { /** * Indicates whether a download is completed. Resolves with the number of downloaded bytes. Rejects if the download has errors. */ completed: Promise; } export type RemoteServerContext = { childProcess: { exec( command: string, options?: {encoding?: BufferEncoding} & ExecOptions, ): Promise>; }; fs: { constants: typeof fsConstants; access(path: string, mode?: number): Promise; pathExists(path: string, mode?: number): Promise; unlink(path: string): Promise; mkdir( path: string, options: {recursive: true} & MkdirOptions, ): Promise; mkdir( path: string, options?: {recursive?: false} & MkdirOptions, ): Promise; rm(path: string, options?: RmOptions): Promise; copyFile(src: string, dest: string, flags?: number): Promise; stat(path: string): Promise; readlink(path: string): Promise; readFile( path: string, options?: {encoding?: BufferEncoding}, ): Promise; readFileBinary(path: string): Promise; // No Buffer, which is not a browser type writeFile( path: string, contents: string, options?: {encoding?: BufferEncoding}, ): Promise; writeFileBinary(path: string, contents: Uint8Array): Promise; }; downloadFile( url: string, dest: string, options?: DownloadFileStartOptions & { onProgressUpdate?: (progressUpdate: DownloadFileUpdate) => void; }, ): Promise; }; /** * This interface exposes all global methods for which an implementation will be provided by Flipper itself */ export interface FlipperLib { isFB: boolean; logger: Logger; enableMenuEntries(menuEntries: NormalizedMenuEntry[]): void; createPaste( args: string | CreatePasteArgs, ): Promise; GK(gatekeeper: string): boolean; selectPlugin( device: Device, client: RealFlipperClient | null, pluginId: string, deeplink: unknown, ): void; writeTextToClipboard(text: string): void; openLink(url: string): void; showNotification(pluginKey: string, notification: Notification): void; DetailsSidebarImplementation?(props: { children: any; width?: number; minWidth?: number; }): ReactElement | null; /** * @returns * Imported file data. * If user cancelled a file selection - undefined. */ importFile(options?: { /** * Default directory to start the file selection from */ defaultPath?: string; /** * List of allowed file extensions */ extensions?: string[]; /** * Open file dialog title */ title?: string; /** * File encoding */ encoding?: FileEncoding; /** * Allow selection of multiple files */ multi?: false; }): Promise; importFile(options?: { defaultPath?: string; extensions?: string[]; title?: string; encoding?: FileEncoding; multi: true; }): Promise; /** * @returns * An exported file path (if available) or a file name. * If user cancelled a file selection - undefined. */ exportFile( /** * New file data */ data: string, options?: { /** * A file path suggestion for a new file. * A dialog to save file will use it as a starting point. * Either a complete path to the newly created file, a path to a directory containing the file, or the file name. */ defaultPath?: string; /** * File encoding */ encoding?: FileEncoding; }, ): Promise; /** * @returns * An exported file path (if available) or a file name. * If user cancelled a file selection - undefined. */ exportFileBinary( /** * New file data */ data: Uint8Array, options?: { /** * A file path suggestion for a new file. * A dialog to save file will use it as a starting point. * Either a complete path to the newly created file, a path to a directory containing the file, or the file name. */ defaultPath?: string; }, ): Promise; paths: { appPath: string; homePath: string; staticPath: string; tempPath: string; }; environmentInfo: { os: EnvironmentInfo['os']; isHeadlessBuild: EnvironmentInfo['isHeadlessBuild']; env: Partial>; }; remoteServerContext: RemoteServerContext; intern: InternAPI; settings: () => { isDarkMode: boolean; }; } interface InternAPI { graphGet: FlipperServerCommands['intern-graph-get']; graphPost: FlipperServerCommands['intern-graph-post']; /** * @deprecated */ isLoggedIn: FlipperServerCommands['is-logged-in']; currentUser: () => Atom; isConnected: () => Atom; } export let flipperLibInstance: FlipperLib | undefined; export function tryGetFlipperLibImplementation(): FlipperLib | undefined { return flipperLibInstance; } export function getFlipperLib(): FlipperLib { if (!flipperLibInstance) { throw new Error('Flipper lib not instantiated'); } return flipperLibInstance; } export function setFlipperLibImplementation(impl: FlipperLib | undefined) { flipperLibInstance = impl; }