Move plugins to "sonar/desktop/plugins"

Summary:
Plugins moved from "sonar/desktop/src/plugins" to "sonar/desktop/plugins".

Fixed all the paths after moving.

New "desktop" folder structure:
- `src` - Flipper desktop app JS code executing in Electron Renderer (Chrome) process.
- `static` - Flipper desktop app JS code executing in Electron Main (Node.js) process.
- `plugins` - Flipper desktop JS plugins.
- `pkg` - Flipper packaging lib and CLI tool.
- `doctor` - Flipper diagnostics lib and CLI tool.
- `scripts` - Build scripts for Flipper desktop app.
- `headless` - Headless version of Flipper desktop app.
- `headless-tests` - Integration tests running agains Flipper headless version.

Reviewed By: mweststrate

Differential Revision: D20344186

fbshipit-source-id: d020da970b2ea1e001f9061a8782bfeb54e31ba0
This commit is contained in:
Anton Nikolaev
2020-03-14 14:26:07 -07:00
committed by Facebook GitHub Bot
parent beb5c85e69
commit 10d990c32c
133 changed files with 106 additions and 77 deletions

View File

@@ -0,0 +1,52 @@
/**
* 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 fs from 'fs';
import path from 'path';
import {BaseDevice, AndroidDevice, IOSDevice} from 'flipper';
import {AppMatchPattern} from '../types';
const extractAppNameFromSelectedApp = (selectedApp: string | null) => {
if (selectedApp == null) {
return null;
} else {
return selectedApp.split('#')[0];
}
};
export const getAppMatchPatterns = (
selectedApp: string | null,
device: BaseDevice,
) => {
return new Promise<Array<AppMatchPattern>>((resolve, reject) => {
const appName = extractAppNameFromSelectedApp(selectedApp);
if (appName === 'Facebook') {
let filename: string;
if (device instanceof AndroidDevice) {
filename = 'facebook-match-patterns-android.json';
} else if (device instanceof IOSDevice) {
filename = 'facebook-match-patterns-ios.json';
} else {
return;
}
const patternsPath = path.join('facebook', filename);
fs.readFile(patternsPath, (err, data) => {
if (err) {
reject(err);
} else {
resolve(JSON.parse(data.toString()));
}
});
} else if (appName != null) {
reject(new Error('No rule for app ' + appName));
} else {
reject(new Error('selectedApp was null'));
}
});
};

View File

@@ -0,0 +1,103 @@
/**
* 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 {
URI,
Bookmark,
AutoCompleteProvider,
AutoCompleteLineItem,
AppMatchPattern,
} from '../types';
export function DefaultProvider(): AutoCompleteProvider {
return {
icon: 'caution',
matchPatterns: new Map<string, URI>(),
};
}
export const bookmarksToAutoCompleteProvider = (
bookmarks: Map<URI, Bookmark>,
) => {
const autoCompleteProvider = {
icon: 'bookmark',
matchPatterns: new Map<string, URI>(),
} as AutoCompleteProvider;
bookmarks.forEach((bookmark, uri) => {
const matchPattern = bookmark.commonName + ' - ' + uri;
autoCompleteProvider.matchPatterns.set(matchPattern, uri);
});
return autoCompleteProvider;
};
export const appMatchPatternsToAutoCompleteProvider = (
appMatchPatterns: Array<AppMatchPattern>,
) => {
const autoCompleteProvider = {
icon: 'mobile',
matchPatterns: new Map<string, URI>(),
};
appMatchPatterns.forEach(appMatchPattern => {
const matchPattern =
appMatchPattern.className + ' - ' + appMatchPattern.pattern;
autoCompleteProvider.matchPatterns.set(
matchPattern,
appMatchPattern.pattern,
);
});
return autoCompleteProvider;
};
export const filterMatchPatterns = (
matchPatterns: Map<string, URI>,
query: URI,
maxItems: number,
) => {
const filteredPatterns = new Map<string, URI>();
for (const [pattern, uri] of matchPatterns) {
if (filteredPatterns.size >= maxItems) {
break;
} else if (pattern.toLowerCase().includes(query.toLowerCase())) {
filteredPatterns.set(pattern, uri);
}
}
return filteredPatterns;
};
const filterProvider = (
provider: AutoCompleteProvider,
query: string,
maxItems: number,
) => {
return {
...provider,
matchPatterns: filterMatchPatterns(provider.matchPatterns, query, maxItems),
};
};
export const filterProvidersToLineItems = (
providers: Array<AutoCompleteProvider>,
query: string,
maxItems: number,
) => {
let itemsLeft = maxItems;
const lineItems = new Array<AutoCompleteLineItem>(0);
for (const provider of providers) {
const filteredProvider = filterProvider(provider, query, itemsLeft);
filteredProvider.matchPatterns.forEach((uri, matchPattern) => {
lineItems.push({
icon: provider.icon,
matchPattern,
uri,
});
});
itemsLeft -= filteredProvider.matchPatterns.size;
}
return lineItems;
};

View File

@@ -0,0 +1,104 @@
/**
* 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 {Bookmark} from '../types';
const FLIPPER_NAVIGATION_PLUGIN_DB = 'flipper_navigation_plugin_db';
const FLIPPER_NAVIGATION_PLUGIN_DB_VERSION = 1;
const BOOKMARKS_KEY = 'bookmarks';
const createBookmarksObjectStore = (db: IDBDatabase) => {
return new Promise<void>((resolve, reject) => {
if (!db.objectStoreNames.contains(BOOKMARKS_KEY)) {
const bookmarksObjectStore = db.createObjectStore(BOOKMARKS_KEY, {
keyPath: 'uri',
});
bookmarksObjectStore.transaction.oncomplete = () => resolve();
bookmarksObjectStore.transaction.onerror = () =>
reject(bookmarksObjectStore.transaction.error);
} else {
resolve();
}
});
};
const initializeNavigationPluginDB = (db: IDBDatabase) => {
return Promise.all([createBookmarksObjectStore(db)]);
};
const openNavigationPluginDB: () => Promise<IDBDatabase> = () => {
return new Promise((resolve, reject) => {
const openRequest = window.indexedDB.open(
FLIPPER_NAVIGATION_PLUGIN_DB,
FLIPPER_NAVIGATION_PLUGIN_DB_VERSION,
);
openRequest.onupgradeneeded = () => {
const db = openRequest.result;
initializeNavigationPluginDB(db).then(() => resolve(db));
};
openRequest.onerror = () => reject(openRequest.error);
openRequest.onsuccess = () => resolve(openRequest.result);
});
};
export const writeBookmarkToDB = (bookmark: Bookmark) => {
return new Promise((resolve, reject) => {
openNavigationPluginDB()
.then((db: IDBDatabase) => {
const bookmarksObjectStore = db
.transaction(BOOKMARKS_KEY, 'readwrite')
.objectStore(BOOKMARKS_KEY);
const request = bookmarksObjectStore.put(bookmark);
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
})
.catch(reject);
});
};
export const readBookmarksFromDB: () => Promise<Map<string, Bookmark>> = () => {
return new Promise((resolve, reject) => {
const bookmarks = new Map();
openNavigationPluginDB()
.then((db: IDBDatabase) => {
const bookmarksObjectStore = db
.transaction(BOOKMARKS_KEY)
.objectStore(BOOKMARKS_KEY);
const request = bookmarksObjectStore.openCursor();
request.onsuccess = () => {
const cursor = request.result;
if (cursor) {
const bookmark = cursor.value;
bookmarks.set(bookmark.uri, bookmark);
cursor.continue();
} else {
resolve(bookmarks);
}
};
request.onerror = () => reject(request.error);
})
.catch(reject);
});
};
export const removeBookmark: (uri: string) => Promise<void> = uri => {
return new Promise<void>((resolve, reject) => {
openNavigationPluginDB()
.then((db: IDBDatabase) => {
const bookmarksObjectStore = db
.transaction(BOOKMARKS_KEY, 'readwrite')
.objectStore(BOOKMARKS_KEY);
const request = bookmarksObjectStore.delete(uri);
request.onsuccess = () => resolve();
request.onerror = () => reject(request.error);
})
.catch(reject);
});
};

View File

@@ -0,0 +1,94 @@
/**
* 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 querystring from 'querystring';
export const validateParameter = (value: string, parameter: string) => {
return (
value &&
(parameterIsNumberType(parameter) ? !isNaN(parseInt(value, 10)) : true) &&
(parameterIsBooleanType(parameter)
? value === 'true' || value === 'false'
: true)
);
};
export const filterOptionalParameters = (uri: string) => {
return uri.replace(/[/&]?([^&?={}\/]*=)?{\?.*?}/g, '');
};
export const parseURIParameters = (query: string) => {
// get parameters from query string and store in Map
const parameters = query
.split('?')
.splice(1)
.join('');
const parametersObj = querystring.parse(parameters);
const parametersMap = new Map<string, string>();
for (const key in parametersObj) {
parametersMap.set(key, parametersObj[key] as string);
}
return parametersMap;
};
export const parameterIsNumberType = (parameter: string) => {
const regExp = /^{(#|\?#)/g;
return regExp.test(parameter);
};
export const parameterIsBooleanType = (parameter: string) => {
const regExp = /^{(!|\?!)/g;
return regExp.test(parameter);
};
export const replaceRequiredParametersWithValues = (
uri: string,
values: Array<string>,
) => {
const parameterRegExp = /{[^?]*?}/g;
const replaceRegExp = /{[^?]*?}/;
let newURI = uri;
let index = 0;
let match = parameterRegExp.exec(uri);
while (match != null) {
newURI = newURI.replace(replaceRegExp, values[index]);
match = parameterRegExp.exec(uri);
index++;
}
return newURI;
};
export const getRequiredParameters = (uri: string) => {
const parameterRegExp = /{[^?]*?}/g;
const matches: Array<string> = [];
let match = parameterRegExp.exec(uri);
while (match != null) {
if (match[0]) {
matches.push(match[0]);
}
match = parameterRegExp.exec(uri);
}
return matches;
};
export const liveEdit = (uri: string, formValues: Array<string>) => {
const parameterRegExp = /({[^?]*?})/g;
const uriArray = uri.split(parameterRegExp);
return uriArray.reduce((acc, uriComponent, idx) => {
if (idx % 2 === 0 || !formValues[(idx - 1) / 2]) {
return acc + uriComponent;
} else {
return acc + formValues[(idx - 1) / 2];
}
});
};
export const stripQueryParameters = (uri: string) => {
return uri.replace(/\?.*$/g, '');
};