Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion extension/.babelrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript"
],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }]
Expand Down
4 changes: 3 additions & 1 deletion extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"test:app": "cross-env BABEL_ENV=test jest test/app",
"test:chrome": "jest test/chrome",
"test:electron": "jest test/electron",
"test": "npm run test:app && npm run build:extension && npm run test:chrome && npm run test:electron"
"test": "npm run test:app && npm run build:extension && npm run test:chrome && npm run test:electron",
"type-check": "tsc --noEmit"
},
"dependencies": {
"@redux-devtools/app": "^1.0.0-8",
Expand All @@ -37,6 +38,7 @@
"@redux-devtools/serialize": "^0.3.0",
"@redux-devtools/slider-monitor": "^2.0.0-8",
"@redux-devtools/utils": "^1.0.0-6",
"@types/jsan": "^3.1.2",
"jsan": "^3.1.13",
"lodash": "^4.17.21",
"react": "^16.14.0",
Expand Down
110 changes: 73 additions & 37 deletions extension/src/app/api/filters.js → extension/src/app/api/filters.ts
Original file line number Diff line number Diff line change
@@ -1,81 +1,104 @@
import mapValues from 'lodash/mapValues';
import { Config } from '../../browser/extension/inject/pageScript';
import { Action } from 'redux';
import { LiftedState, PerformAction } from '@redux-devtools/instrument';

export const FilterState = {
export type FilterStateValue =
| 'DO_NOT_FILTER'
| 'BLACKLIST_SPECIFIC'
| 'WHITELIST_SPECIFIC';

export const FilterState: { [K in FilterStateValue]: FilterStateValue } = {
DO_NOT_FILTER: 'DO_NOT_FILTER',
BLACKLIST_SPECIFIC: 'BLACKLIST_SPECIFIC',
WHITELIST_SPECIFIC: 'WHITELIST_SPECIFIC',
};

export function getLocalFilter(config) {
function isArray(arg: unknown): arg is readonly unknown[] {
return Array.isArray(arg);
}

interface LocalFilter {
readonly whitelist: string | undefined;
readonly blacklist: string | undefined;
}

export function getLocalFilter(config: Config): LocalFilter | undefined {
if (config.actionsBlacklist || config.actionsWhitelist) {
return {
whitelist: Array.isArray(config.actionsWhitelist)
whitelist: isArray(config.actionsWhitelist)
? config.actionsWhitelist.join('|')
: config.actionsWhitelist,
blacklist: Array.isArray(config.actionsBlacklist)
blacklist: isArray(config.actionsBlacklist)
? config.actionsBlacklist.join('|')
: config.actionsBlacklist,
};
}
return undefined;
}

export const noFiltersApplied = (localFilter) =>
export const noFiltersApplied = (localFilter: LocalFilter | undefined) =>
// !predicate &&
!localFilter &&
(!window.devToolsOptions ||
!window.devToolsOptions.filter ||
window.devToolsOptions.filter === FilterState.DO_NOT_FILTER);

export function isFiltered(action, localFilter) {
export function isFiltered<A extends Action<unknown>>(
action: A | string,
localFilter: LocalFilter | undefined
) {
if (
noFiltersApplied(localFilter) ||
(typeof action !== 'string' && typeof action.type.match !== 'function')
(typeof action !== 'string' &&
typeof (action.type as string).match !== 'function')
) {
return false;
}

const { whitelist, blacklist } = localFilter || window.devToolsOptions || {};
const actionType = action.type || action;
const actionType = ((action as A).type || action) as string;
return (
(whitelist && !actionType.match(whitelist)) ||
(blacklist && actionType.match(blacklist))
);
}

function filterActions(actionsById, actionSanitizer) {
function filterActions<A extends Action<unknown>>(
actionsById: { [p: number]: PerformAction<A> },
actionSanitizer: ((action: A, id: number) => A) | undefined
): { [p: number]: PerformAction<A> } {
if (!actionSanitizer) return actionsById;
return mapValues(actionsById, (action, id) => ({
...action,
action: actionSanitizer(action.action, id),
action: actionSanitizer(action.action, id as unknown as number),
}));
}

function filterStates(computedStates, stateSanitizer) {
function filterStates<S>(
computedStates: { state: S; error?: string | undefined }[],
stateSanitizer: ((state: S, index: number) => S) | undefined
) {
if (!stateSanitizer) return computedStates;
return computedStates.map((state, idx) => ({
...state,
state: stateSanitizer(state.state, idx),
}));
}

export function filterState(
state,
type,
localFilter,
stateSanitizer,
actionSanitizer,
nextActionId,
predicate
) {
if (type === 'ACTION') {
return !stateSanitizer ? state : stateSanitizer(state, nextActionId - 1);
} else if (type !== 'STATE') return state;

export function filterState<S, A extends Action<unknown>>(
state: LiftedState<S, A, unknown>,
localFilter: LocalFilter | undefined,
stateSanitizer: ((state: S, index: number) => S) | undefined,
actionSanitizer: ((action: A, id: number) => A) | undefined,
predicate: ((state: S, action: A) => boolean) | undefined
): LiftedState<S, A, unknown> {
if (predicate || !noFiltersApplied(localFilter)) {
const filteredStagedActionIds = [];
const filteredComputedStates = [];
const sanitizedActionsById = actionSanitizer && {};
const filteredStagedActionIds: number[] = [];
const filteredComputedStates: { state: S; error?: string | undefined }[] =
[];
const sanitizedActionsById: { [p: number]: PerformAction<A> } | undefined =
actionSanitizer && {};
const { actionsById } = state;
const { computedStates } = state;

Expand All @@ -97,7 +120,7 @@ export function filterState(
: liftedState
);
if (actionSanitizer) {
sanitizedActionsById[id] = {
sanitizedActionsById![id] = {
...liftedAction,
action: actionSanitizer(currAction, id),
};
Expand All @@ -120,14 +143,27 @@ export function filterState(
};
}

export function startingFrom(
sendingActionId,
state,
localFilter,
stateSanitizer,
actionSanitizer,
predicate
) {
export interface PartialLiftedState<S, A extends Action<unknown>> {
readonly actionsById: { [actionId: number]: PerformAction<A> };
readonly computedStates: { state: S; error?: string }[];
readonly stagedActionIds: readonly number[];
readonly currentStateIndex: number;
readonly nextActionId: number;
readonly committedState?: S;
}

export function startingFrom<S, A extends Action<unknown>>(
sendingActionId: number,
state: LiftedState<S, A, unknown>,
localFilter: LocalFilter | undefined,
stateSanitizer: (<S>(state: S, index: number) => S) | undefined,
actionSanitizer:
| (<A extends Action<unknown>>(action: A, id: number) => A)
| undefined,
predicate:
| (<S, A extends Action<unknown>>(state: S, action: A) => boolean)
| undefined
): LiftedState<S, A, unknown> | PartialLiftedState<S, A> | undefined {
const stagedActionIds = state.stagedActionIds;
if (sendingActionId <= stagedActionIds[1]) return state;
const index = stagedActionIds.indexOf(sendingActionId);
Expand All @@ -137,7 +173,7 @@ export function startingFrom(
const filteredStagedActionIds = shouldFilter ? [0] : stagedActionIds;
const actionsById = state.actionsById;
const computedStates = state.computedStates;
const newActionsById = {};
const newActionsById: { [key: number]: PerformAction<A> } = {};
const newComputedStates = [];
let key;
let currAction;
Expand Down
5 changes: 0 additions & 5 deletions extension/src/app/api/generateInstanceId.js

This file was deleted.

5 changes: 5 additions & 0 deletions extension/src/app/api/generateInstanceId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let id = 0;

export default function generateId(instanceId: number | undefined) {
return instanceId || ++id;
}
74 changes: 0 additions & 74 deletions extension/src/app/api/importState.js

This file was deleted.

Loading