Remove fs and os usage from Mobile Builds plugin

Summary: Changelog: Expose env info and FS rm command to flipper plugins.

Reviewed By: mweststrate

Differential Revision: D32988478

fbshipit-source-id: 3d0233f9eb34d3478b07e39b9401c0e30ca95135
This commit is contained in:
Andrey Goncharov
2021-12-10 06:34:37 -08:00
committed by Facebook GitHub Bot
parent adb2573a1f
commit c96558a524
15 changed files with 166 additions and 6 deletions

View File

@@ -21,6 +21,7 @@ export {sleep} from './utils/sleep';
export {timeout} from './utils/timeout'; export {timeout} from './utils/timeout';
export {isTest} from './utils/isTest'; export {isTest} from './utils/isTest';
export {assertNever} from './utils/assertNever'; export {assertNever} from './utils/assertNever';
export {fsConstants} from './utils/fsConstants';
export { export {
logPlatformSuccessRate, logPlatformSuccessRate,
reportPlatformFailures, reportPlatformFailures,

View File

@@ -140,6 +140,7 @@ export type FlipperServerCommands = {
path: string, path: string,
options?: {recursive?: boolean} & MkdirOptions, options?: {recursive?: boolean} & MkdirOptions,
) => Promise<string | void>; ) => Promise<string | void>;
'node-api-fs-rm': (path: string, options?: RmOptions) => Promise<void>;
'node-api-fs-copyFile': ( 'node-api-fs-copyFile': (
src: string, src: string,
dest: string, dest: string,
@@ -332,6 +333,10 @@ export interface MkdirOptions {
mode?: string | number; mode?: string | number;
} }
export interface RmOptions {
maxRetries?: number;
}
export interface DownloadFileStartOptions { export interface DownloadFileStartOptions {
method?: 'GET' | 'POST'; method?: 'GET' | 'POST';
timeout?: number; timeout?: number;

View File

@@ -69,6 +69,19 @@ export type ProcessConfig = {
launcherEnabled: boolean; launcherEnabled: boolean;
}; };
export type Platform =
| 'aix'
| 'android'
| 'darwin'
| 'freebsd'
| 'haiku'
| 'linux'
| 'openbsd'
| 'sunos'
| 'win32'
| 'cygwin'
| 'netbsd';
export type EnvironmentInfo = { export type EnvironmentInfo = {
processId: number; processId: number;
isProduction: boolean; isProduction: boolean;
@@ -77,7 +90,7 @@ export type EnvironmentInfo = {
appVersion: string; appVersion: string;
os: { os: {
arch: string; arch: string;
platform: NodeJS.Platform; platform: Platform;
unixname: string; unixname: string;
}; };
versions: { versions: {

View File

@@ -0,0 +1,67 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
// https://github.com/nodejs/node/blob/b66a75a3a4361614dde9bc1a52d7e9021b4efc26/typings/internalBinding/constants.d.ts
export const fsConstants = {
UV_FS_SYMLINK_DIR: 1,
UV_FS_SYMLINK_JUNCTION: 2,
O_RDONLY: 0,
O_WRONLY: 1,
O_RDWR: 2,
UV_DIRENT_UNKNOWN: 0,
UV_DIRENT_FILE: 1,
UV_DIRENT_DIR: 2,
UV_DIRENT_LINK: 3,
UV_DIRENT_FIFO: 4,
UV_DIRENT_SOCKET: 5,
UV_DIRENT_CHAR: 6,
UV_DIRENT_BLOCK: 7,
S_IFMT: 61440,
S_IFREG: 32768,
S_IFDIR: 16384,
S_IFCHR: 8192,
S_IFBLK: 24576,
S_IFIFO: 4096,
S_IFLNK: 40960,
S_IFSOCK: 49152,
O_CREAT: 512,
O_EXCL: 2048,
UV_FS_O_FILEMAP: 0,
O_NOCTTY: 131072,
O_TRUNC: 1024,
O_APPEND: 8,
O_DIRECTORY: 1048576,
O_NOFOLLOW: 256,
O_SYNC: 128,
O_DSYNC: 4194304,
O_SYMLINK: 2097152,
O_NONBLOCK: 4,
S_IRWXU: 448,
S_IRUSR: 256,
S_IWUSR: 128,
S_IXUSR: 64,
S_IRWXG: 56,
S_IRGRP: 32,
S_IWGRP: 16,
S_IXGRP: 8,
S_IRWXO: 7,
S_IROTH: 4,
S_IWOTH: 2,
S_IXOTH: 1,
F_OK: 0,
R_OK: 4,
W_OK: 2,
X_OK: 1,
UV_FS_COPYFILE_EXCL: 1,
COPYFILE_EXCL: 1,
UV_FS_COPYFILE_FICLONE: 2,
COPYFILE_FICLONE: 2,
UV_FS_COPYFILE_FICLONE_FORCE: 4,
COPYFILE_FICLONE_FORCE: 4,
};

View File

@@ -13,7 +13,6 @@
"@emotion/css": "^11.5.0", "@emotion/css": "^11.5.0",
"@emotion/react": "^11.6.0", "@emotion/react": "^11.6.0",
"@reach/observe-rect": "^1.2.0", "@reach/observe-rect": "^1.2.0",
"@types/uuid": "^8.3.1",
"eventemitter3": "^4.0.7", "eventemitter3": "^4.0.7",
"flipper-common": "0.0.0", "flipper-common": "0.0.0",
"immer": "^9.0.6", "immer": "^9.0.6",
@@ -27,6 +26,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/string-natural-compare": "^3.0.2", "@types/string-natural-compare": "^3.0.2",
"@types/uuid": "^8.3.3",
"jest-mock-console": "^1.2.3", "jest-mock-console": "^1.2.3",
"typescript": "^4.4.4" "typescript": "^4.4.4"
}, },

View File

@@ -70,6 +70,7 @@ test('Correct top level API exposed', () => {
"usePlugin", "usePlugin",
"useTrackedCallback", "useTrackedCallback",
"useValue", "useValue",
"uuid",
"withTrackingScope", "withTrackingScope",
] ]
`); `);

View File

@@ -133,6 +133,7 @@ export {createTablePlugin} from './utils/createTablePlugin';
export {textContent} from './utils/textContent'; export {textContent} from './utils/textContent';
import * as path from './utils/path'; import * as path from './utils/path';
export {path}; export {path};
export * from './utils/uuid';
// It's not ideal that this exists in flipper-plugin sources directly, // It's not ideal that this exists in flipper-plugin sources directly,
// but is the least pain for plugin authors. // but is the least pain for plugin authors.

View File

@@ -21,6 +21,9 @@ import {
DownloadFileStartOptions, DownloadFileStartOptions,
DownloadFileStartResponse, DownloadFileStartResponse,
DownloadFileUpdate, DownloadFileUpdate,
RmOptions,
fsConstants,
EnvironmentInfo,
} from 'flipper-common'; } from 'flipper-common';
export type FileEncoding = 'utf-8' | 'base64'; export type FileEncoding = 'utf-8' | 'base64';
@@ -57,7 +60,9 @@ export type RemoteServerContext = {
path: string, path: string,
options?: {recursive?: false} & MkdirOptions, options?: {recursive?: false} & MkdirOptions,
): Promise<void>; ): Promise<void>;
rm(path: string, options?: RmOptions): Promise<void>;
copyFile(src: string, dest: string, flags?: number): Promise<void>; copyFile(src: string, dest: string, flags?: number): Promise<void>;
constants: typeof fsConstants;
}; };
downloadFile( downloadFile(
url: string, url: string,
@@ -150,6 +155,10 @@ export interface FlipperLib {
paths: { paths: {
homePath: string; homePath: string;
appPath: string; appPath: string;
tempPath: string;
};
environmentInfo: {
os: EnvironmentInfo['os'];
}; };
remoteServerContext: RemoteServerContext; remoteServerContext: RemoteServerContext;
} }

View File

@@ -14,7 +14,11 @@ import {
act as testingLibAct, act as testingLibAct,
} from '@testing-library/react'; } from '@testing-library/react';
import {queries} from '@testing-library/dom'; import {queries} from '@testing-library/dom';
import {BundledPluginDetails, InstalledPluginDetails} from 'flipper-common'; import {
BundledPluginDetails,
fsConstants,
InstalledPluginDetails,
} from 'flipper-common';
import { import {
RealFlipperClient, RealFlipperClient,
@@ -388,6 +392,14 @@ export function createMockFlipperLib(options?: StartPluginOptions): FlipperLib {
paths: { paths: {
appPath: process.cwd(), appPath: process.cwd(),
homePath: `/dev/null`, homePath: `/dev/null`,
tempPath: `/dev/null`,
},
environmentInfo: {
os: {
arch: 'Test',
unixname: 'test',
platform: 'linux',
},
}, },
remoteServerContext: { remoteServerContext: {
childProcess: { childProcess: {
@@ -398,7 +410,9 @@ export function createMockFlipperLib(options?: StartPluginOptions): FlipperLib {
pathExists: jest.fn(), pathExists: jest.fn(),
unlink: jest.fn(), unlink: jest.fn(),
mkdir: jest.fn(), mkdir: jest.fn(),
rm: jest.fn(),
copyFile: jest.fn(), copyFile: jest.fn(),
constants: fsConstants,
}, },
downloadFile: jest.fn(), downloadFile: jest.fn(),
}, },

View File

@@ -0,0 +1,11 @@
/**
* Copyright (c) Facebook, Inc. and its 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 {v4 as uuid} from 'uuid';
export {uuid};

View File

@@ -28,6 +28,7 @@
"open": "^8.3.0", "open": "^8.3.0",
"openssl-wrapper": "^0.3.4", "openssl-wrapper": "^0.3.4",
"promisify-child-process": "^4.1.1", "promisify-child-process": "^4.1.1",
"rimraf": "^3.0.2",
"rsocket-core": "^0.0.27", "rsocket-core": "^0.0.27",
"rsocket-flowable": "^0.0.27", "rsocket-flowable": "^0.0.27",
"rsocket-tcp-server": "^0.0.25", "rsocket-tcp-server": "^0.0.25",
@@ -43,6 +44,7 @@
"devDependencies": { "devDependencies": {
"@types/memorystream": "^0.3.0", "@types/memorystream": "^0.3.0",
"@types/node": "^15.12.5", "@types/node": "^15.12.5",
"@types/rimraf": "^3.0.2",
"@types/tmp": "^0.2.2", "@types/tmp": "^0.2.2",
"memorystream": "^0.3.1", "memorystream": "^0.3.1",
"tmp": "^0.2.1" "tmp": "^0.2.1"

View File

@@ -46,6 +46,8 @@ import {
import {commandNodeApiExec} from './commands/NodeApiExec'; import {commandNodeApiExec} from './commands/NodeApiExec';
import {commandDownloadFileStartFactory} from './commands/DownloadFile'; import {commandDownloadFileStartFactory} from './commands/DownloadFile';
import {promises} from 'fs'; import {promises} from 'fs';
// Electron 11 runs on Node 12 which does not support fs.promises.rm
import rm from 'rimraf';
const {access, copyFile, mkdir, unlink} = promises; const {access, copyFile, mkdir, unlink} = promises;
@@ -230,6 +232,12 @@ export class FlipperServerImpl implements FlipperServer {
}, },
'node-api-fs-unlink': unlink, 'node-api-fs-unlink': unlink,
'node-api-fs-mkdir': mkdir, 'node-api-fs-mkdir': mkdir,
'node-api-fs-rm': async (path, {maxRetries} = {}) =>
new Promise<void>((resolve, reject) =>
rm(path, {disableGlob: true, maxBusyTries: maxRetries}, (err) =>
err ? reject(err) : resolve(),
),
),
'node-api-fs-copyFile': copyFile, 'node-api-fs-copyFile': copyFile,
// TODO: Do we need API to cancel an active download? // TODO: Do we need API to cancel an active download?
'download-file-start': commandDownloadFileStartFactory( 'download-file-start': commandDownloadFileStartFactory(

View File

@@ -14,8 +14,10 @@ import {
import { import {
BufferEncoding, BufferEncoding,
ExecOptions, ExecOptions,
fsConstants,
Logger, Logger,
MkdirOptions, MkdirOptions,
RmOptions,
} from 'flipper-common'; } from 'flipper-common';
import type {Store} from '../../reducers'; import type {Store} from '../../reducers';
import createPaste from '../../fb-stubs/createPaste'; import createPaste from '../../fb-stubs/createPaste';
@@ -71,6 +73,10 @@ export function initializeFlipperLibImplementation(
paths: { paths: {
appPath: renderHost.serverConfig.paths.appPath, appPath: renderHost.serverConfig.paths.appPath,
homePath: renderHost.serverConfig.paths.homePath, homePath: renderHost.serverConfig.paths.homePath,
tempPath: renderHost.serverConfig.paths.tempPath,
},
environmentInfo: {
os: renderHost.serverConfig.environmentInfo.os,
}, },
remoteServerContext: { remoteServerContext: {
childProcess: { childProcess: {
@@ -95,6 +101,8 @@ export function initializeFlipperLibImplementation(
path, path,
options, options,
)) as RemoteServerContext['fs']['mkdir'], )) as RemoteServerContext['fs']['mkdir'],
rm: async (path: string, options?: RmOptions) =>
renderHost.flipperServer.exec('node-api-fs-rm', path, options),
copyFile: async (src: string, dest: string, flags?: number) => copyFile: async (src: string, dest: string, flags?: number) =>
renderHost.flipperServer.exec( renderHost.flipperServer.exec(
'node-api-fs-copyFile', 'node-api-fs-copyFile',
@@ -102,6 +110,7 @@ export function initializeFlipperLibImplementation(
dest, dest,
flags, flags,
), ),
constants: fsConstants,
}, },
downloadFile: downloadFileFactory(renderHost), downloadFile: downloadFileFactory(renderHost),
}, },

View File

@@ -3046,6 +3046,14 @@
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
"@types/rimraf@^3.0.2":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-3.0.2.tgz#a63d175b331748e5220ad48c901d7bbf1f44eef8"
integrity sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==
dependencies:
"@types/glob" "*"
"@types/node" "*"
"@types/rsocket-core@*", "@types/rsocket-core@^0.0.7": "@types/rsocket-core@*", "@types/rsocket-core@^0.0.7":
version "0.0.7" version "0.0.7"
resolved "https://registry.yarnpkg.com/@types/rsocket-core/-/rsocket-core-0.0.7.tgz#e9ed6d9ec918ec7a9aab0c48fefbb74b33712235" resolved "https://registry.yarnpkg.com/@types/rsocket-core/-/rsocket-core-0.0.7.tgz#e9ed6d9ec918ec7a9aab0c48fefbb74b33712235"
@@ -3174,6 +3182,11 @@
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f"
integrity sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg== integrity sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==
"@types/uuid@^8.3.3":
version "8.3.3"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.3.tgz#c6a60686d953dbd1b1d45e66f4ecdbd5d471b4d0"
integrity sha512-0LbEEx1zxrYB3pgpd1M5lEhLcXjKJnYghvhTRgaBeUivLHMDM1TzF3IJ6hXU2+8uA4Xz+5BA63mtZo5DjVT8iA==
"@types/verror@^1.10.3": "@types/verror@^1.10.3":
version "1.10.4" version "1.10.4"
resolved "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.4.tgz#805c0612b3a0c124cf99f517364142946b74ba3b" resolved "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.4.tgz#805c0612b3a0c124cf99f517364142946b74ba3b"
@@ -6795,9 +6808,9 @@ flow-parser@0.*:
integrity sha512-IVHejqogTgZL2e206twVsdfX5he6mXS5F0AY315ao+6rEifbElEoVWKLYdEBsVl7QMp4buPbMe5FqXSdYQMUSQ== integrity sha512-IVHejqogTgZL2e206twVsdfX5he6mXS5F0AY315ao+6rEifbElEoVWKLYdEBsVl7QMp4buPbMe5FqXSdYQMUSQ==
follow-redirects@^1.14.0: follow-redirects@^1.14.0:
version "1.14.5" version "1.14.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.5.tgz#f09a5848981d3c772b5392309778523f8d85c381" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.6.tgz#8cfb281bbc035b3c067d6cd975b0f6ade6e855cd"
integrity sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA== integrity sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==
for-in@^1.0.2: for-in@^1.0.2:
version "1.0.2" version "1.0.2"

View File

@@ -1160,6 +1160,12 @@ path.normalize('/foo/bar//baz/asdf/quux/..');
// Returns: '/foo/bar/baz/asdf' // Returns: '/foo/bar/baz/asdf'
``` ```
### uuid
Usage: `uuid()`
Returns UUID V4.
## TestUtils ## TestUtils
The object `TestUtils` as exposed from `flipper-plugin` exposes utilities to write unit tests for Sandy plugins. The object `TestUtils` as exposed from `flipper-plugin` exposes utilities to write unit tests for Sandy plugins.