diff --git a/desktop/flipper-common/src/server-types.tsx b/desktop/flipper-common/src/server-types.tsx index 344b344a7..8c3e86bed 100644 --- a/desktop/flipper-common/src/server-types.tsx +++ b/desktop/flipper-common/src/server-types.tsx @@ -132,6 +132,18 @@ export type IOSDeviceParams = { }; export type FlipperServerCommands = { + 'node-api-fs-access': (path: string, mode?: number) => Promise; + 'node-api-fs-pathExists': (path: string, mode?: number) => Promise; + 'node-api-fs-unlink': (path: string) => Promise; + 'node-api-fs-mkdir': ( + path: string, + options?: {recursive?: boolean} & MkdirOptions, + ) => Promise; + 'node-api-fs-copyFile': ( + src: string, + dest: string, + flags?: number, + ) => Promise; /** * @throws ExecError */ @@ -310,6 +322,10 @@ export type BufferEncoding = | 'binary' | 'hex'; +export interface MkdirOptions { + mode?: string | number; +} + export type FlipperServerConfig = { gatekeepers: Record; env: Partial>; diff --git a/desktop/flipper-plugin/src/plugin/FlipperLib.tsx b/desktop/flipper-plugin/src/plugin/FlipperLib.tsx index 0be2da53b..fde710068 100644 --- a/desktop/flipper-plugin/src/plugin/FlipperLib.tsx +++ b/desktop/flipper-plugin/src/plugin/FlipperLib.tsx @@ -13,7 +13,12 @@ import {NormalizedMenuEntry} from './MenuEntry'; import {RealFlipperClient} from './Plugin'; import {Notification} from './Notification'; import {DetailSidebarProps} from '../ui/DetailSidebar'; -import {ExecOptions, ExecOut, BufferEncoding} from 'flipper-common'; +import { + ExecOptions, + ExecOut, + BufferEncoding, + MkdirOptions, +} from 'flipper-common'; export type FileEncoding = 'utf-8' | 'base64'; @@ -31,7 +36,18 @@ export type RemoteNodeAPI = { ): Promise>; }; fs: { - // TODO: Fill me + 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; + copyFile(src: string, dest: string, flags?: number): Promise; }; }; diff --git a/desktop/flipper-plugin/src/test-utils/test-utils.tsx b/desktop/flipper-plugin/src/test-utils/test-utils.tsx index b81ee33b7..68f01d3af 100644 --- a/desktop/flipper-plugin/src/test-utils/test-utils.tsx +++ b/desktop/flipper-plugin/src/test-utils/test-utils.tsx @@ -393,7 +393,13 @@ export function createMockFlipperLib(options?: StartPluginOptions): FlipperLib { childProcess: { exec: jest.fn(), }, - fs: {}, + fs: { + access: jest.fn(), + pathExists: jest.fn(), + unlink: jest.fn(), + mkdir: jest.fn(), + copyFile: jest.fn(), + }, }, }; } diff --git a/desktop/flipper-server-core/src/FlipperServerImpl.tsx b/desktop/flipper-server-core/src/FlipperServerImpl.tsx index 7f049dbb6..316a0f0b1 100644 --- a/desktop/flipper-server-core/src/FlipperServerImpl.tsx +++ b/desktop/flipper-server-core/src/FlipperServerImpl.tsx @@ -44,6 +44,7 @@ import { internGraphPOSTAPIRequest, } from './fb-stubs/internRequests'; import {commandNodeApiExec} from './commands/NodeApiExec'; +import {access, copyFile, mkdir, unlink} from 'fs/promises'; export const SERVICE_FLIPPER = 'flipper.oAuthToken'; @@ -215,6 +216,18 @@ export class FlipperServerImpl implements FlipperServer { private commandHandler: FlipperServerCommands = { 'node-api-exec': commandNodeApiExec, + 'node-api-fs-access': access, + 'node-api-fs-pathExists': async (path, mode) => { + try { + await access(path, mode); + return true; + } catch { + return false; + } + }, + 'node-api-fs-unlink': unlink, + 'node-api-fs-mkdir': mkdir, + 'node-api-fs-copyFile': copyFile, 'get-config': async () => this.config, 'get-changelog': getChangelog, 'device-list': async () => { diff --git a/desktop/flipper-ui-core/src/utils/flipperLibImplementation.tsx b/desktop/flipper-ui-core/src/utils/flipperLibImplementation.tsx index ea9dea2ca..de79f2bb8 100644 --- a/desktop/flipper-ui-core/src/utils/flipperLibImplementation.tsx +++ b/desktop/flipper-ui-core/src/utils/flipperLibImplementation.tsx @@ -8,7 +8,12 @@ */ import {_setFlipperLibImplementation, RemoteNodeAPI} from 'flipper-plugin'; -import type {BufferEncoding, ExecOptions, Logger} from 'flipper-common'; +import type { + BufferEncoding, + ExecOptions, + Logger, + MkdirOptions, +} from 'flipper-common'; import type {Store} from '../reducers'; import createPaste from '../fb-stubs/createPaste'; import type BaseDevice from '../devices/BaseDevice'; @@ -75,7 +80,30 @@ export function initializeFlipperLibImplementation( options, )) as RemoteNodeAPI['childProcess']['exec'], }, - fs: {}, + fs: { + access: async (path: string, mode?: number) => + renderHost.flipperServer.exec('node-api-fs-access', path, mode), + pathExists: async (path: string, mode?: number) => + renderHost.flipperServer.exec('node-api-fs-pathExists', path, mode), + unlink: async (path: string) => + renderHost.flipperServer.exec('node-api-fs-unlink', path), + mkdir: (async ( + path: string, + options?: {recursive?: boolean} & MkdirOptions, + ) => + renderHost.flipperServer.exec( + 'node-api-fs-mkdir', + path, + options, + )) as RemoteNodeAPI['fs']['mkdir'], + copyFile: async (src: string, dest: string, flags?: number) => + renderHost.flipperServer.exec( + 'node-api-fs-copyFile', + src, + dest, + flags, + ), + }, }, }); }