setup webserver for flipper-server
Summary: This sets up the metro bundler for flipper-server, to be able to serve the front end. Note that this is a setup that is only relevant for development purposes Done in this diff: * setup metro * setup fast refresh * setup nodemon to be able to refresh on server changes Not done in this diff * Setup FlipperServerImpl in the flipper-server * Load flipper-ui-core in flipper-ui-browser * Load plugins * Support options, env vars etc etc * Make flipper-server stand alone (it is largely self contained, but still requires some static resources like theming) Reviewed By: passy, aigoncharov Differential Revision: D32626137 fbshipit-source-id: 47f580356ddf0993392d3b583082b187661727e9
This commit is contained in:
committed by
Facebook GitHub Bot
parent
2b81be6c29
commit
0dfc73da93
@@ -9,13 +9,27 @@
|
||||
"types": "lib/index.d.ts",
|
||||
"license": "MIT",
|
||||
"bugs": "https://github.com/facebook/flipper/issues",
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"express": "^4.15.2",
|
||||
"flipper-pkg-lib": "0.0.0",
|
||||
"fs-extra": "^9.0.0",
|
||||
"p-filter": "^2.1.0",
|
||||
"socket.io": "^4.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.13",
|
||||
"metro": "^0.66.2",
|
||||
"nodemon": "^2.0.15",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.4.4"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
"scripts": {
|
||||
"reset": "rimraf lib *.tsbuildinfo",
|
||||
"build": "tsc -b",
|
||||
"prepack": "yarn reset && yarn build"
|
||||
"prepack": "yarn reset && yarn build",
|
||||
"start": "cross-env NODE_ENV=development nodemon --watch './src/*.tsx' --exec '../ts-node' src/index.tsx"
|
||||
},
|
||||
"files": [
|
||||
"lib/**/*"
|
||||
|
||||
@@ -7,6 +7,13 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
export function helloWorld() {
|
||||
return true;
|
||||
}
|
||||
// TODO: currently flipper-server is only suitable for development,
|
||||
// needs to be come independently runnable, prebundled, distributed, etc!
|
||||
// in future require conditionally
|
||||
import {startWebServerDev} from './startWebServerDev';
|
||||
import chalk from 'chalk';
|
||||
|
||||
startWebServerDev().catch((e) => {
|
||||
console.error(chalk.red('Server error: '), e);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
165
desktop/flipper-server/src/startWebServerDev.tsx
Normal file
165
desktop/flipper-server/src/startWebServerDev.tsx
Normal file
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* 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 {hostname} from 'os';
|
||||
import chalk from 'chalk';
|
||||
import express, {Express} from 'express';
|
||||
import http from 'http';
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import socketio from 'socket.io';
|
||||
import {getWatchFolders} from 'flipper-pkg-lib';
|
||||
import Metro from 'metro';
|
||||
import pFilter from 'p-filter';
|
||||
|
||||
const PORT = 52342;
|
||||
const rootDir = path.resolve(__dirname, '..', '..');
|
||||
const staticDir = path.join(rootDir, 'static');
|
||||
const babelTransformationsDir = path.resolve(
|
||||
rootDir,
|
||||
'babel-transformer',
|
||||
'src',
|
||||
);
|
||||
|
||||
const uiSourceDirs = [
|
||||
'flipper-ui-browser',
|
||||
'flipper-ui-core',
|
||||
'flipper-plugin',
|
||||
'flipper-common',
|
||||
];
|
||||
|
||||
// This file is heavily inspired by scripts/start-dev-server.ts!
|
||||
export async function startWebServerDev() {
|
||||
checkDevServer();
|
||||
// await prepareDefaultPlugins(
|
||||
// process.env.FLIPPER_RELEASE_CHANNEL === 'insiders',
|
||||
// );
|
||||
// await ensurePluginFoldersWatchable();
|
||||
const {app, server} = await startAssetServer(PORT);
|
||||
const socket = await addWebsocket(server);
|
||||
await startMetroServer(app, server, socket);
|
||||
// await compileMain();
|
||||
// if (dotenv && dotenv.parsed) {
|
||||
// console.log('✅ Loaded env vars from .env file: ', dotenv.parsed);
|
||||
// }
|
||||
// shutdownElectron = launchElectron(port);
|
||||
console.log(
|
||||
`Flipper DEV server started at http://localhost:${PORT}/index.web.dev.html`,
|
||||
);
|
||||
}
|
||||
|
||||
function looksLikeDevServer(): boolean {
|
||||
const hn = hostname();
|
||||
if (/^devvm.*\.facebook\.com$/.test(hn)) {
|
||||
return true;
|
||||
}
|
||||
if (hn.endsWith('.od.fbinfra.net')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkDevServer() {
|
||||
if (looksLikeDevServer()) {
|
||||
console.log(
|
||||
chalk.red(
|
||||
`✖ It looks like you're trying to start Flipper on your OnDemand or DevServer, which is not supported. Please run this in a local checkout on your laptop or desktop instead.`,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function startAssetServer(
|
||||
port: number,
|
||||
): Promise<{app: Express; server: http.Server}> {
|
||||
const app = express();
|
||||
|
||||
app.use((_req, res, next) => {
|
||||
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
|
||||
res.header('Expires', '-1');
|
||||
res.header('Pragma', 'no-cache');
|
||||
next();
|
||||
});
|
||||
|
||||
app.get('/', (_req, res) => {
|
||||
fs.readFile(path.join(staticDir, 'index.web.dev.html'), (_err, content) => {
|
||||
res.end(content);
|
||||
});
|
||||
});
|
||||
|
||||
app.use(express.static(staticDir));
|
||||
|
||||
const server = http.createServer(app);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
server.listen(port, 'localhost', () => resolve({app, server}));
|
||||
});
|
||||
}
|
||||
|
||||
async function addWebsocket(server: http.Server) {
|
||||
const io = new socketio.Server(server); // 3.1.0 socket.io doesn't have type definitions
|
||||
|
||||
io.on('connection', (client) => {
|
||||
console.log(chalk.green(`Client connected ${client.id}`));
|
||||
});
|
||||
|
||||
// Refresh the app on changes.
|
||||
// When Fast Refresh enabled, reloads are performed by HMRClient, so don't need to watch manually here.
|
||||
// if (!process.env.FLIPPER_FAST_REFRESH) {
|
||||
// await startWatchChanges(io);
|
||||
// }
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
async function startMetroServer(
|
||||
app: Express,
|
||||
server: http.Server,
|
||||
socket: socketio.Server,
|
||||
) {
|
||||
const watchFolders = await dedupeFolders(
|
||||
(
|
||||
await Promise.all(
|
||||
uiSourceDirs.map((dir) => getWatchFolders(path.resolve(rootDir, dir))),
|
||||
)
|
||||
).flat(),
|
||||
);
|
||||
// console.log('Source dirs\n\t' + watchFolders.join('\n\t'));
|
||||
const baseConfig = await Metro.loadConfig();
|
||||
const config = Object.assign({}, baseConfig, {
|
||||
projectRoot: rootDir,
|
||||
watchFolders,
|
||||
transformer: {
|
||||
...baseConfig.transformer,
|
||||
babelTransformerPath: path.join(babelTransformationsDir, 'transform-app'),
|
||||
},
|
||||
resolver: {
|
||||
...baseConfig.resolver,
|
||||
resolverMainFields: ['flipperBundlerEntry', 'module', 'main'],
|
||||
blacklistRE: /\.native\.js$/,
|
||||
sourceExts: ['js', 'jsx', 'ts', 'tsx', 'json', 'mjs', 'cjs'],
|
||||
},
|
||||
watch: true,
|
||||
});
|
||||
const connectMiddleware = await Metro.createConnectMiddleware(config);
|
||||
app.use(connectMiddleware.middleware);
|
||||
connectMiddleware.attachHmrServer(server);
|
||||
app.use(function (err: any, _req: any, _res: any, next: any) {
|
||||
console.error(chalk.red('\n\nCompile error in client bundle\n'), err);
|
||||
socket.local.emit('hasErrors', err.toString());
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
async function dedupeFolders(paths: string[]): Promise<string[]> {
|
||||
return pFilter(
|
||||
paths.filter((value, index, self) => self.indexOf(value) === index),
|
||||
(f) => fs.pathExists(f),
|
||||
);
|
||||
}
|
||||
@@ -7,6 +7,9 @@
|
||||
"references": [
|
||||
{
|
||||
"path": "../flipper-server-core"
|
||||
},
|
||||
{
|
||||
"path": "../pkg-lib"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -10,7 +10,12 @@
|
||||
"license": "MIT",
|
||||
"bugs": "https://github.com/facebook/flipper/issues",
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"devDependencies": {
|
||||
"invariant": "^2.2.4",
|
||||
"metro-runtime": "^0.66.2",
|
||||
"pretty-format": "^27.3.1",
|
||||
"react-refresh": "^0.10.0"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
"scripts": {
|
||||
"reset": "rimraf lib *.tsbuildinfo",
|
||||
|
||||
277
desktop/flipper-ui-browser/src/HMRClient.tsx
Normal file
277
desktop/flipper-ui-browser/src/HMRClient.tsx
Normal file
@@ -0,0 +1,277 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* * * * * * * ** * * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * ** * * * * * * * * *
|
||||
* This implementation of HMR Client is based on React Native implementation with some code commented out: *
|
||||
* https://github.com/facebook/react-native/blob/master/Libraries/Utilities/HMRClient.js *
|
||||
* * * * * * * ** * * * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * ** * * * * * * * * *
|
||||
*/
|
||||
|
||||
// // const DevSettings = require('./DevSettings');
|
||||
import invariant from 'invariant';
|
||||
// @ts-ignore
|
||||
import {default as MetroHMRClient} from 'metro-runtime/src/modules/HMRClient';
|
||||
// // const Platform = require('./Platform');
|
||||
import prettyFormat from 'pretty-format';
|
||||
|
||||
const pendingEntryPoints: string[] = [];
|
||||
let hmrClient: any = null;
|
||||
let hmrUnavailableReason: null | string = null;
|
||||
let currentCompileErrorMessage: null | string = null;
|
||||
let didConnect = false;
|
||||
const pendingLogs: [string, any][] = [];
|
||||
|
||||
/**
|
||||
* HMR Client that receives from the server HMR updates and propagates them
|
||||
* runtime to reflects those changes.
|
||||
*/
|
||||
const HMRClient = {
|
||||
enable() {
|
||||
if (hmrUnavailableReason !== null) {
|
||||
// If HMR became unavailable while you weren't using it,
|
||||
// explain why when you try to turn it on.
|
||||
// This is an error (and not a warning) because it is shown
|
||||
// in response to a direct user action.
|
||||
throw new Error(hmrUnavailableReason);
|
||||
}
|
||||
|
||||
invariant(hmrClient, 'Expected HMRClient.setup() call at startup.');
|
||||
//// const LoadingView = require('./LoadingView');
|
||||
|
||||
// We use this for internal logging only.
|
||||
// It doesn't affect the logic.
|
||||
hmrClient.send(JSON.stringify({type: 'log-opt-in'}));
|
||||
|
||||
// When toggling Fast Refresh on, we might already have some stashed updates.
|
||||
// Since they'll get applied now, we'll show a banner.
|
||||
const hasUpdates = hmrClient.hasPendingUpdates();
|
||||
|
||||
if (hasUpdates) {
|
||||
//// LoadingView.showMessage('Refreshing...', 'refresh');
|
||||
console.log('Loading start: Refreshing...');
|
||||
}
|
||||
try {
|
||||
hmrClient.enable();
|
||||
} finally {
|
||||
if (hasUpdates) {
|
||||
//// LoadingView.hide();
|
||||
console.log('Loading end');
|
||||
}
|
||||
}
|
||||
|
||||
// There could be a compile error while Fast Refresh was off,
|
||||
// but we ignored it at the time. Show it now.
|
||||
showCompileError();
|
||||
},
|
||||
|
||||
disable() {
|
||||
invariant(hmrClient, 'Expected HMRClient.setup() call at startup.');
|
||||
hmrClient.disable();
|
||||
},
|
||||
|
||||
registerBundle(requestUrl: string) {
|
||||
invariant(hmrClient, 'Expected HMRClient.setup() call at startup.');
|
||||
pendingEntryPoints.push(requestUrl);
|
||||
registerBundleEntryPoints(hmrClient);
|
||||
},
|
||||
|
||||
log(level: string, data: any) {
|
||||
if (!hmrClient) {
|
||||
// Catch a reasonable number of early logs
|
||||
// in case hmrClient gets initialized later.
|
||||
pendingLogs.push([level, data]);
|
||||
if (pendingLogs.length > 100) {
|
||||
pendingLogs.shift();
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
hmrClient.send(
|
||||
JSON.stringify({
|
||||
type: 'log',
|
||||
level,
|
||||
data: data.map((item: any) =>
|
||||
typeof item === 'string'
|
||||
? item
|
||||
: prettyFormat(item, {
|
||||
escapeString: true,
|
||||
highlight: true,
|
||||
maxDepth: 3,
|
||||
min: true,
|
||||
plugins: [(prettyFormat as any).plugins.ReactElement],
|
||||
}),
|
||||
),
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
// If sending logs causes any failures we want to silently ignore them
|
||||
// to ensure we do not cause infinite-logging loops.
|
||||
}
|
||||
},
|
||||
|
||||
// Called once by the bridge on startup, even if Fast Refresh is off.
|
||||
// It creates the HMR client but doesn't actually set up the socket yet.
|
||||
setup(
|
||||
platform: string,
|
||||
bundleEntry: string,
|
||||
host: string,
|
||||
port: string,
|
||||
isEnabled: boolean,
|
||||
) {
|
||||
invariant(platform, 'Missing required parameter `platform`');
|
||||
invariant(bundleEntry, 'Missing required parameter `bundleEntry`');
|
||||
invariant(host, 'Missing required parameter `host`');
|
||||
invariant(!hmrClient, 'Cannot initialize hmrClient twice');
|
||||
|
||||
//// const LoadingView = require('./LoadingView');
|
||||
|
||||
const wsHost = port !== null && port !== '' ? `${host}:${port}` : host;
|
||||
const client = new MetroHMRClient(`ws://${wsHost}/hot`);
|
||||
hmrClient = client;
|
||||
|
||||
pendingEntryPoints.push(
|
||||
`ws://${wsHost}/hot?bundleEntry=${bundleEntry}&platform=${platform}`,
|
||||
);
|
||||
|
||||
client.on('connection-error', (e: any) => {
|
||||
let error = `Cannot connect to the Metro server.
|
||||
Try the following to fix the issue:
|
||||
- Ensure that the Metro server is running and available on the same network`;
|
||||
|
||||
error += `
|
||||
- Ensure that your device/emulator is connected to your machine and has USB debugging enabled - run 'adb devices' to see a list of connected devices
|
||||
- If you're on a physical device connected to the same machine, run 'adb reverse tcp:8081 tcp:8081' to forward requests from your device
|
||||
- If your device is on the same Wi-Fi network, set 'Debug server host & port for device' in 'Dev settings' to your machine's IP address and the port of the local dev server - e.g. 10.0.1.1:8081`;
|
||||
|
||||
error += `
|
||||
URL: ${host}:${port}
|
||||
Error: ${e.message}`;
|
||||
|
||||
setHMRUnavailableReason(error);
|
||||
});
|
||||
|
||||
client.on('update-start', ({isInitialUpdate}: any) => {
|
||||
currentCompileErrorMessage = null;
|
||||
didConnect = true;
|
||||
|
||||
if (client.isEnabled() && !isInitialUpdate) {
|
||||
//// LoadingView.showMessage('Refreshing...', 'refresh');
|
||||
console.log('Loading start: Refreshing...');
|
||||
}
|
||||
});
|
||||
|
||||
client.on('update', () => {});
|
||||
|
||||
client.on('update-done', () => {
|
||||
//// LoadingView.hide();
|
||||
console.log('Loading end');
|
||||
});
|
||||
|
||||
client.on('error', (data: any) => {
|
||||
//// LoadingView.hide();
|
||||
console.log('Loading end');
|
||||
|
||||
if (data.type === 'GraphNotFoundError') {
|
||||
client.close();
|
||||
setHMRUnavailableReason(
|
||||
'The Metro server has restarted since the last edit. Reload to reconnect.',
|
||||
);
|
||||
} else if (data.type === 'RevisionNotFoundError') {
|
||||
client.close();
|
||||
setHMRUnavailableReason(
|
||||
'The Metro server and the client are out of sync. Reload to reconnect.',
|
||||
);
|
||||
} else {
|
||||
currentCompileErrorMessage = `${data.type} ${data.message}`;
|
||||
if (client.isEnabled()) {
|
||||
showCompileError();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.on('close', (_data: any) => {
|
||||
//// LoadingView.hide();
|
||||
console.log('Loading end');
|
||||
setHMRUnavailableReason('Disconnected from the Metro server.');
|
||||
});
|
||||
|
||||
if (isEnabled) {
|
||||
HMRClient.enable();
|
||||
} else {
|
||||
HMRClient.disable();
|
||||
}
|
||||
|
||||
registerBundleEntryPoints(hmrClient);
|
||||
flushEarlyLogs(hmrClient);
|
||||
},
|
||||
};
|
||||
|
||||
function setHMRUnavailableReason(reason: string) {
|
||||
invariant(hmrClient, 'Expected HMRClient.setup() call at startup.');
|
||||
if (hmrUnavailableReason !== null) {
|
||||
// Don't show more than one warning.
|
||||
return;
|
||||
}
|
||||
hmrUnavailableReason = reason;
|
||||
|
||||
// We only want to show a warning if Fast Refresh is on *and* if we ever
|
||||
// previously managed to connect successfully. We don't want to show
|
||||
// the warning to native engineers who use cached bundles without Metro.
|
||||
if (hmrClient.isEnabled() && didConnect) {
|
||||
console.warn(reason);
|
||||
// (Not using the `warning` module to prevent a Buck cycle.)
|
||||
}
|
||||
}
|
||||
|
||||
function registerBundleEntryPoints(client: any) {
|
||||
if (hmrUnavailableReason) {
|
||||
// // DevSettings.reload('Bundle Splitting – Metro disconnected');
|
||||
console.log('Bundle Spliiting - Metro disconnected');
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingEntryPoints.length > 0) {
|
||||
client.send(
|
||||
JSON.stringify({
|
||||
type: 'register-entrypoints',
|
||||
entryPoints: pendingEntryPoints,
|
||||
}),
|
||||
);
|
||||
pendingEntryPoints.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function flushEarlyLogs(_client: any) {
|
||||
try {
|
||||
pendingLogs.forEach(([level, data]) => {
|
||||
HMRClient.log(level, data);
|
||||
});
|
||||
} finally {
|
||||
pendingLogs.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function showCompileError() {
|
||||
if (currentCompileErrorMessage === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message = currentCompileErrorMessage;
|
||||
currentCompileErrorMessage = null;
|
||||
|
||||
const error = new Error(message);
|
||||
// Symbolicating compile errors is wasted effort
|
||||
// because the stack trace is meaningless:
|
||||
(error as any).preventSymbolication = true;
|
||||
(window as any).flipperShowError?.(message);
|
||||
throw error;
|
||||
}
|
||||
|
||||
export default HMRClient;
|
||||
53
desktop/flipper-ui-browser/src/index-fast-refresh.tsx
Normal file
53
desktop/flipper-ui-browser/src/index-fast-refresh.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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 {default as HmrClient} from './HMRClient';
|
||||
// @ts-ignore
|
||||
import {default as ReactRefreshRuntime} from 'react-refresh/runtime';
|
||||
|
||||
HmrClient.setup(
|
||||
'web',
|
||||
(window as any).flipperConfig.entryPoint,
|
||||
'localhost',
|
||||
window.location.port,
|
||||
true,
|
||||
);
|
||||
|
||||
ReactRefreshRuntime.injectIntoGlobalHook(window);
|
||||
|
||||
const Refresh = {
|
||||
performFullRefresh(reason: string) {
|
||||
console.log('Perform full refresh', reason);
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
createSignatureFunctionForTransform:
|
||||
ReactRefreshRuntime.createSignatureFunctionForTransform,
|
||||
|
||||
isLikelyComponentType: ReactRefreshRuntime.isLikelyComponentType,
|
||||
|
||||
getFamilyByType: ReactRefreshRuntime.getFamilyByType,
|
||||
|
||||
register: ReactRefreshRuntime.register,
|
||||
|
||||
performReactRefresh() {
|
||||
if (ReactRefreshRuntime.hasUnrecoverableErrors()) {
|
||||
console.error('Fast refresh - Unrecolverable');
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
ReactRefreshRuntime.performReactRefresh();
|
||||
console.log('Perform react refresh');
|
||||
},
|
||||
};
|
||||
|
||||
(require as any).Refresh = Refresh;
|
||||
|
||||
// eslint-disable-next-line import/no-commonjs
|
||||
require('./index.tsx');
|
||||
@@ -7,6 +7,4 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
export function helloWorld() {
|
||||
return true;
|
||||
}
|
||||
document.getElementById('root')!.innerText = 'flipper-ui-browser started';
|
||||
|
||||
117
desktop/static/index.web.dev.html
Normal file
117
desktop/static/index.web.dev.html
Normal file
@@ -0,0 +1,117 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link id="flipper-theme-import" rel="stylesheet">
|
||||
<title>Flipper</title>
|
||||
<script>
|
||||
window.flipperConfig = {
|
||||
theme: 'light',
|
||||
entryPoint: 'flipper-ui-browser/src/index-fast-refresh.bundle?platform=web&dev=true&minify=false',
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
||||
#loading {
|
||||
-webkit-app-region: drag;
|
||||
z-index: 999999;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: 50px;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
color: #525252;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.__infinity-dev-box-error {
|
||||
background-color: red;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
z-index: 10;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root">
|
||||
<div id="loading">
|
||||
Loading...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="__infinity-dev-box __infinity-dev-box-error" hidden>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
// FIXME: needed to make Metro work
|
||||
window.global = window;
|
||||
global.electronRequire = window.require;
|
||||
|
||||
let suppressErrors = false;
|
||||
|
||||
const socket = io(location.origin);
|
||||
|
||||
socket.on('refresh', () => {
|
||||
location.reload();
|
||||
});
|
||||
|
||||
socket.on('hasErrors', (html) => {
|
||||
openError(html);
|
||||
suppressErrors = true;
|
||||
});
|
||||
|
||||
function openError(text) {
|
||||
if (suppressErrors) {
|
||||
return;
|
||||
}
|
||||
|
||||
const box = document.querySelector('.__infinity-dev-box-error');
|
||||
box.removeAttribute('hidden');
|
||||
box.textContent = text;
|
||||
}
|
||||
window.flipperShowError = openError;
|
||||
|
||||
// load correct theme (n.b. this doesn't handle system value specifically, will assume light in such cases)
|
||||
try {
|
||||
if (window.flipperConfig.theme === 'dark') {
|
||||
document.getElementById('flipper-theme-import').href="themes/dark.css";
|
||||
} else {
|
||||
document.getElementById('flipper-theme-import').href="themes/light.css";
|
||||
}
|
||||
} catch(e) {
|
||||
console.error("Failed to initialize theme", e);
|
||||
document.getElementById('flipper-theme-import').href="themes/light.css";
|
||||
}
|
||||
|
||||
function init() {
|
||||
const script = document.createElement('script');
|
||||
script.src = window.flipperConfig.entryPoint;
|
||||
|
||||
script.onerror = (e) => {
|
||||
openError('Script failure. Check Chrome console for more info. ');
|
||||
};
|
||||
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
init();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3309,6 +3309,11 @@ abab@^2.0.3, abab@^2.0.5:
|
||||
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a"
|
||||
integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
||||
|
||||
abort-controller@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
|
||||
@@ -3606,6 +3611,14 @@ anymatch@^3.0.3:
|
||||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
anymatch@~3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
|
||||
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
|
||||
dependencies:
|
||||
normalize-path "^3.0.0"
|
||||
picomatch "^2.0.4"
|
||||
|
||||
app-builder-bin@3.5.13:
|
||||
version "3.5.13"
|
||||
resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.13.tgz#6dd7f4de34a4e408806f99b8c7d6ef1601305b7e"
|
||||
@@ -4192,6 +4205,11 @@ base@^0.11.1:
|
||||
mixin-deep "^1.2.0"
|
||||
pascalcase "^0.1.1"
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||
|
||||
bl@^1.0.0, bl@^4.0.3, bl@^4.1.0, bl@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-5.0.0.tgz#6928804a41e9da9034868e1c50ca88f21f57aea2"
|
||||
@@ -4282,7 +4300,7 @@ braces@^2.3.1:
|
||||
split-string "^3.0.2"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
braces@^3.0.1:
|
||||
braces@^3.0.1, braces@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
@@ -4592,6 +4610,21 @@ chardet@^0.7.0:
|
||||
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
||||
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
|
||||
|
||||
chokidar@^3.5.2:
|
||||
version "3.5.2"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
|
||||
integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
|
||||
dependencies:
|
||||
anymatch "~3.1.2"
|
||||
braces "~3.0.2"
|
||||
glob-parent "~5.1.2"
|
||||
is-binary-path "~2.1.0"
|
||||
is-glob "~4.0.1"
|
||||
normalize-path "~3.0.0"
|
||||
readdirp "~3.6.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
chownr@^1.1.1:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||
@@ -6830,6 +6863,11 @@ fsevents@^2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
|
||||
integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
@@ -6911,7 +6949,7 @@ github-slugger@^1.2.1:
|
||||
dependencies:
|
||||
emoji-regex ">=6.0.0 <=6.1.1"
|
||||
|
||||
glob-parent@^5.1.2:
|
||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
@@ -7285,6 +7323,11 @@ ieee754@^1.1.13, ieee754@^1.2.1:
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
|
||||
ignore-by-default@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
|
||||
integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk=
|
||||
|
||||
ignore-walk@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-4.0.1.tgz#fc840e8346cf88a3a9380c5b17933cd8f4d39fa3"
|
||||
@@ -7481,6 +7524,13 @@ is-bigint@^1.0.1:
|
||||
dependencies:
|
||||
has-bigints "^1.0.1"
|
||||
|
||||
is-binary-path@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
|
||||
integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
|
||||
dependencies:
|
||||
binary-extensions "^2.0.0"
|
||||
|
||||
is-boolean-object@^1.1.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719"
|
||||
@@ -7619,7 +7669,7 @@ 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-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3:
|
||||
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
|
||||
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
|
||||
@@ -9850,6 +9900,29 @@ node-releases@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5"
|
||||
integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==
|
||||
|
||||
nodemon@^2.0.15:
|
||||
version "2.0.15"
|
||||
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.15.tgz#504516ce3b43d9dc9a955ccd9ec57550a31a8d4e"
|
||||
integrity sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==
|
||||
dependencies:
|
||||
chokidar "^3.5.2"
|
||||
debug "^3.2.7"
|
||||
ignore-by-default "^1.0.1"
|
||||
minimatch "^3.0.4"
|
||||
pstree.remy "^1.1.8"
|
||||
semver "^5.7.1"
|
||||
supports-color "^5.5.0"
|
||||
touch "^3.1.0"
|
||||
undefsafe "^2.0.5"
|
||||
update-notifier "^5.1.0"
|
||||
|
||||
nopt@~1.0.10:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
|
||||
integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=
|
||||
dependencies:
|
||||
abbrev "1"
|
||||
|
||||
normalize-package-data@^2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
|
||||
@@ -9877,7 +9950,7 @@ normalize-path@^2.1.1:
|
||||
dependencies:
|
||||
remove-trailing-separator "^1.0.1"
|
||||
|
||||
normalize-path@^3.0.0:
|
||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
@@ -10401,7 +10474,7 @@ picomatch@^2.0.4, picomatch@^2.0.5:
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
|
||||
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
|
||||
|
||||
picomatch@^2.2.3:
|
||||
picomatch@^2.2.1, picomatch@^2.2.3:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
|
||||
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
|
||||
@@ -10639,6 +10712,11 @@ psl@^1.1.33:
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
|
||||
integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
|
||||
|
||||
pstree.remy@^1.1.8:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a"
|
||||
integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==
|
||||
|
||||
pump@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
|
||||
@@ -11266,6 +11344,11 @@ react-redux@^7.2.6:
|
||||
prop-types "^15.7.2"
|
||||
react-is "^17.0.2"
|
||||
|
||||
react-refresh@^0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.10.0.tgz#2f536c9660c0b9b1d500684d9e52a65e7404f7e3"
|
||||
integrity sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==
|
||||
|
||||
react-refresh@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
|
||||
@@ -11417,6 +11500,13 @@ readdir-glob@^1.0.0:
|
||||
dependencies:
|
||||
minimatch "^3.0.4"
|
||||
|
||||
readdirp@~3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
|
||||
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
|
||||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
realpath-native@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866"
|
||||
@@ -11942,7 +12032,7 @@ semver-diff@^3.1.1:
|
||||
dependencies:
|
||||
semver "^6.3.0"
|
||||
|
||||
"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
|
||||
"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.1:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
@@ -12205,7 +12295,7 @@ socket.io-parser@~4.0.4:
|
||||
component-emitter "~1.3.0"
|
||||
debug "~4.3.1"
|
||||
|
||||
socket.io@*, socket.io@^4.4.0:
|
||||
socket.io@*, socket.io@^4.3.1, socket.io@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.4.0.tgz#8140a0db2c22235f88a6dceb867e4d5c9bd70507"
|
||||
integrity sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==
|
||||
@@ -12542,7 +12632,7 @@ sumchecker@^3.0.1:
|
||||
dependencies:
|
||||
debug "^4.1.0"
|
||||
|
||||
supports-color@^5.3.0:
|
||||
supports-color@^5.3.0, supports-color@^5.5.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
||||
@@ -12805,6 +12895,13 @@ toidentifier@1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
||||
|
||||
touch@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b"
|
||||
integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==
|
||||
dependencies:
|
||||
nopt "~1.0.10"
|
||||
|
||||
tough-cookie@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
|
||||
@@ -13040,6 +13137,11 @@ unbzip2-stream@^1.0.9:
|
||||
buffer "^5.2.1"
|
||||
through "^2.3.8"
|
||||
|
||||
undefsafe@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
|
||||
integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==
|
||||
|
||||
unicode-canonical-property-names-ecmascript@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
|
||||
|
||||
Reference in New Issue
Block a user