mirror of
https://github.com/BorysLevytskyi/BitwiseCmd.git
synced 2025-12-17 18:32:11 +01:00
Refactor towards modular structure
This commit is contained in:
@@ -1,86 +0,0 @@
|
||||
import * as expression from './expression/expression';
|
||||
import React from 'react';
|
||||
import uuid from 'uuid/v4';
|
||||
import { CommandInput, CmdShell } from './core/cmd';
|
||||
import AppState from './core/AppState';
|
||||
import {ParsingError, IpAddress, ipAddressParser, IpAddressWithSubnetMask, ParsedIpObject} from './ipaddress/ip'
|
||||
import ErrorResultView from './components/results/ErrorResultView';
|
||||
import HelpResultView from './components/results/HelpResultView';
|
||||
import AboutResultView from './components/results/AboutResultView';
|
||||
import WhatsnewResultView from './components/results/WhatsNewResultView';
|
||||
import TextResultView from './components/results/TextResultView';
|
||||
import IpAddressView from './components/results/IpAddressView';
|
||||
import UnknownInputResultView from './components/results/UnknownInputResultView';
|
||||
import BitwiseOperationExpressionView from './components/results/expressions/BitwiseOperationExpressionView';
|
||||
|
||||
export default {
|
||||
initialize (cmd: CmdShell, appState: AppState) {
|
||||
|
||||
cmd.debugMode = appState.debugMode;
|
||||
appState.onChange(() => cmd.debugMode = appState.debugMode);
|
||||
|
||||
cmd.command("help", (c: CommandInput) => appState.addCommandResult(c.input, <HelpResultView />));
|
||||
cmd.command("clear", () => appState.clearCommandResults());
|
||||
cmd.command("em", () => appState.toggleEmphasizeBytes());
|
||||
cmd.command("dark", () => appState.setUiTheme('dark'));
|
||||
cmd.command("light", () => appState.setUiTheme('light'));
|
||||
cmd.command("midnight", () => appState.setUiTheme('midnight'));
|
||||
cmd.command("about", (c: CommandInput) => appState.addCommandResult(c.input, <AboutResultView />));
|
||||
cmd.command("whatsnew", (c: CommandInput) => appState.addCommandResult(c.input, <WhatsnewResultView />));
|
||||
cmd.command("guid", (c: CommandInput) => appState.addCommandResult(c.input, <TextResultView text={uuid()} />));
|
||||
cmd.command("-notrack", () => {});
|
||||
cmd.command("-debug", (c: CommandInput) => {
|
||||
appState.toggleDebugMode();
|
||||
appState.addCommandResult(c.input, <TextResultView text={`Debug Mode: ${appState.debugMode}`}/>);
|
||||
});
|
||||
|
||||
|
||||
// Ip Addresses
|
||||
cmd.command({
|
||||
canHandle: (input:string) => ipAddressParser.parse(input) != null,
|
||||
handle: function(c: CommandInput) {
|
||||
var result = ipAddressParser.parse(c.input);
|
||||
|
||||
if(result == null)
|
||||
return;
|
||||
|
||||
if(result instanceof ParsingError) {
|
||||
appState.addCommandResult(c.input, <ErrorResultView errorMessage={result.errorMessage} />);
|
||||
return;
|
||||
}
|
||||
|
||||
const ipAddresses : IpAddress[] = [];
|
||||
|
||||
(result as ParsedIpObject[]).forEach(r => {
|
||||
if(r instanceof IpAddressWithSubnetMask)
|
||||
{
|
||||
ipAddresses.push(r.ipAddress);
|
||||
ipAddresses.push(r.createSubnetMaskIp());
|
||||
}
|
||||
else if(r instanceof IpAddress) {
|
||||
ipAddresses.push(r);
|
||||
}
|
||||
});
|
||||
|
||||
appState.addCommandResult(c.input, <IpAddressView ipAddresses={ipAddresses} />);
|
||||
}
|
||||
})
|
||||
|
||||
// Bitwise Expressions
|
||||
cmd.command({
|
||||
canHandle: (input:string) => expression.parser.canParse(input),
|
||||
handle: function(c: CommandInput) {
|
||||
var expr = expression.parser.parse(c.input);
|
||||
appState.addCommandResult(c.input, <BitwiseOperationExpressionView expression={expr!} emphasizeBytes={appState.emphasizeBytes} />);
|
||||
}
|
||||
})
|
||||
|
||||
// Last command handler reports that input is unknown
|
||||
cmd.command({
|
||||
canHandle: () => true,
|
||||
handle: (c: CommandInput) => appState.addCommandResult(c.input, <UnknownInputResultView input={c.input}/>)
|
||||
});
|
||||
|
||||
cmd.onError((input: string, err: Error) => appState.addCommandResult(input, <ErrorResultView errorMessage={err.toString()} />));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import cmd from '../core/cmd';
|
||||
import cmd from '../../shell/cmd';
|
||||
|
||||
type CommandLinkProps = {
|
||||
command?:string;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NumericOperand, ListOfNumbersExpression, BitwiseOperationExpression, ExpressionOperand } from '../../../expression/expression';
|
||||
import { ExpressionInputItem, ExpressionInput } from '../../../expression/expression-interfaces';
|
||||
import { NumericOperand, ListOfNumbersExpression, BitwiseOperationExpression, ExpressionOperand } from '../expression';
|
||||
import { ExpressionInputItem, ExpressionInput } from '../expression-interfaces';
|
||||
|
||||
type Config = {
|
||||
emphasizeBytes: boolean;
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import formatter from '../../../core/formatter';
|
||||
import BinaryStringView, { FlipBitEventArg } from '../BinaryString';
|
||||
import formatter from '../../core/formatter';
|
||||
import BinaryStringView, { FlipBitEventArg } from '../../core/components/BinaryString';
|
||||
import BitwiseExpressionViewModel from './BitwiseExpressionModel';
|
||||
import { ExpressionInput, ExpressionInputItem } from '../../../expression/expression-interfaces';
|
||||
import { ExpressionOperand, NumericOperand } from '../../../expression/expression';
|
||||
import { ExpressionInput, ExpressionInputItem } from '../expression-interfaces';
|
||||
import { ExpressionOperand, NumericOperand } from '../expression';
|
||||
|
||||
type BitwiseOperationExpressionViewProps = {
|
||||
expression: ExpressionInput;
|
||||
21
src/expression/module.tsx
Normal file
21
src/expression/module.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import AppState from '../shell/AppState';
|
||||
import { CmdShell, CommandInput } from '../shell/cmd';
|
||||
import BitwiseOperationExpressionView from './components/BitwiseOperationExpressionView';
|
||||
import {parser} from './expression';
|
||||
|
||||
const expressionAppModule = {
|
||||
setup: function(appState: AppState, cmd: CmdShell) {
|
||||
|
||||
// Bitwise Expressions
|
||||
cmd.command({
|
||||
canHandle: (input:string) => parser.canParse(input),
|
||||
handle: function(c: CommandInput) {
|
||||
var expr = parser.parse(c.input);
|
||||
appState.addCommandResult(c.input, <BitwiseOperationExpressionView expression={expr!} emphasizeBytes={appState.emphasizeBytes} />);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default expressionAppModule;
|
||||
@@ -1,61 +1,41 @@
|
||||
import AppState from './core/AppState';
|
||||
import appStateStore from './core/appStateStore';
|
||||
import cmd from './core/cmd';
|
||||
import commands from './commands';
|
||||
import AppRoot from './AppRoot';
|
||||
import hash from './core/hash';
|
||||
import cmd, { CommandInput } from './shell/cmd';
|
||||
import AppRoot from './shell/components/AppRoot';
|
||||
import log from 'loglevel';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import networkingAppModule from './networking/module';
|
||||
import expressionAppModule from './expression/module';
|
||||
import shellModule from './shell/module';
|
||||
import bootstrapAppData from './shell/startup';
|
||||
import UnknownInputResultView from './shell/components/UnknownInputResultView';
|
||||
|
||||
const env = window.location.host === "bitwisecmd.com" ? 'prod' : 'stage';
|
||||
setupLogger(env);
|
||||
|
||||
const appState = createAppState(env);
|
||||
|
||||
commands.initialize(cmd, appState);
|
||||
const appData = bootstrapAppData();
|
||||
|
||||
initializeModules();
|
||||
executeStartupCommands();
|
||||
|
||||
var root = <AppRoot appState={appState} />;
|
||||
var root = <AppRoot appState={appData.appState} />;
|
||||
ReactDOM.render(root, document.getElementById('root'));
|
||||
|
||||
log.debug("started");
|
||||
|
||||
function createAppState(env:string) {
|
||||
var stateData = appStateStore.getPersistedData();
|
||||
const appState = new AppState(stateData, env);
|
||||
appStateStore.watch(appState);
|
||||
log.debug("appState initialized", appState);
|
||||
return appState;
|
||||
}
|
||||
|
||||
function setupLogger(env: Env) {
|
||||
if(env != 'prod'){
|
||||
log.setLevel("debug");
|
||||
log.debug(`Log level is set to debug. Env: ${env}`)
|
||||
} else {
|
||||
log.setLevel("warn");
|
||||
}
|
||||
}
|
||||
|
||||
function executeStartupCommands() {
|
||||
var hashArgs = hash.getArgs(window.location.hash);
|
||||
|
||||
var startupCommands = ['help', '127.0.0.1 192.168.0.0/8', '1|2&6','4 0b1000000 0x80'];
|
||||
|
||||
if(appState.wasOldVersion) {
|
||||
startupCommands = ["whatsnew"];
|
||||
}
|
||||
|
||||
if(hashArgs.length > 0) {
|
||||
startupCommands = hashArgs;
|
||||
}
|
||||
|
||||
log.debug('Executing startup commands', startupCommands);
|
||||
|
||||
startupCommands.forEach(cmd.execute.bind(cmd));
|
||||
log.debug("Executing startup commands", appData.startupCommands);
|
||||
appData.startupCommands.forEach(cmd.execute.bind(cmd));
|
||||
}
|
||||
|
||||
type Env = 'prod' | 'stage';
|
||||
function initializeModules() {
|
||||
shellModule.setup(appData.appState, cmd);
|
||||
networkingAppModule.setup(appData.appState, cmd);
|
||||
expressionAppModule.setup(appData.appState, cmd);
|
||||
|
||||
// Last command handler reports that input is unknown
|
||||
cmd.command({
|
||||
canHandle: () => true,
|
||||
handle: (c: CommandInput) => appData.appState.addCommandResult(c.input, <UnknownInputResultView input={c.input}/>)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { IpAddress, OctetNumber, getNetworkClass } from '../../ipaddress/ip';
|
||||
import { IpAddress, OctetNumber, getNetworkClass } from '../ip';
|
||||
import formatter from '../../core/formatter'
|
||||
import BinaryStringView from './BinaryString';
|
||||
import BinaryStringView from '../../core/components/BinaryString';
|
||||
import './IpAddressView.css';
|
||||
type IpAddressViewProps = {
|
||||
ipAddresses: IpAddress[]
|
||||
47
src/networking/module.tsx
Normal file
47
src/networking/module.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import React from 'react';
|
||||
import AppState from '../shell/AppState';
|
||||
import { CmdShell, CommandInput } from '../shell/cmd';
|
||||
import ErrorResultView from '../shell/components/ErrorResultView';
|
||||
import IpAddressView from './components/IpAddressView';
|
||||
import { ipAddressParser, ParsingError, IpAddress, ParsedIpObject, IpAddressWithSubnetMask } from './ip';
|
||||
import log from 'loglevel';
|
||||
|
||||
const networkingAppModule = {
|
||||
setup: function(appState: AppState, cmd: CmdShell) {
|
||||
|
||||
// Add Ip Address commands
|
||||
cmd.command({
|
||||
canHandle: (input:string) => ipAddressParser.parse(input) != null,
|
||||
handle: function(c: CommandInput) {
|
||||
var result = ipAddressParser.parse(c.input);
|
||||
|
||||
if(result == null)
|
||||
return;
|
||||
|
||||
if(result instanceof ParsingError) {
|
||||
appState.addCommandResult(c.input, <ErrorResultView errorMessage={result.errorMessage} />);
|
||||
return;
|
||||
}
|
||||
|
||||
const ipAddresses : IpAddress[] = [];
|
||||
|
||||
(result as ParsedIpObject[]).forEach(r => {
|
||||
if(r instanceof IpAddressWithSubnetMask)
|
||||
{
|
||||
ipAddresses.push(r.ipAddress);
|
||||
ipAddresses.push(r.createSubnetMaskIp());
|
||||
}
|
||||
else if(r instanceof IpAddress) {
|
||||
ipAddresses.push(r);
|
||||
}
|
||||
});
|
||||
|
||||
appState.addCommandResult(c.input, <IpAddressView ipAddresses={ipAddresses} />);
|
||||
}
|
||||
});
|
||||
|
||||
log.debug();
|
||||
}
|
||||
}
|
||||
|
||||
export default networkingAppModule;
|
||||
@@ -1,5 +1,4 @@
|
||||
import { CmdShell, ICommandHandler } from "./cmd";
|
||||
import { func } from "prop-types";
|
||||
|
||||
describe("CmdShell", () => {
|
||||
it("simple command", () => {
|
||||
@@ -1,4 +1,4 @@
|
||||
import is from './is';
|
||||
import is from '../core/is';
|
||||
import log from 'loglevel';
|
||||
|
||||
export type CommandInput = {
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import InputBox from './components/InputBox';
|
||||
import DisplayResultView from './components/DisplayResultView';
|
||||
import AppState, { CommandResultView } from './core/AppState';
|
||||
import cmd from './core/cmd';
|
||||
import InputBox from './InputBox';
|
||||
import DisplayResultView from './DisplayResultView';
|
||||
import AppState, { CommandResultView } from '../AppState';
|
||||
import cmd from '../cmd';
|
||||
import log from 'loglevel';
|
||||
import Indicators from './components/Indicators';
|
||||
import hash from './core/hash';
|
||||
import Indicators from './Indicators';
|
||||
import hash from '../../core/hash';
|
||||
|
||||
type AppRootProps = {
|
||||
appState: AppState,
|
||||
@@ -33,7 +33,7 @@ export default class AppRoot extends React.Component<AppRootProps, AppRootState>
|
||||
}
|
||||
|
||||
getResultViews() : JSX.Element[] {
|
||||
log.debug('getting result views')
|
||||
|
||||
var results = this.state.commandResults.map((r, i) =>
|
||||
<DisplayResultView key={r.key} input={r.input} inputHash={hash.encodeHash(r.input)} appState={this.props.appState}>
|
||||
{r.view}
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import AppState from '../core/AppState';
|
||||
import AppState from '../AppState';
|
||||
|
||||
|
||||
type DisplayResultProps = {
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import CommandLink from '../CommandLink';
|
||||
import CommandLink from '../../core/components/CommandLink';
|
||||
import './HelpResultView.css';
|
||||
|
||||
function HelpResultView() {
|
||||
@@ -1,4 +1,4 @@
|
||||
import AppState from "../core/AppState";
|
||||
import AppState from "../AppState";
|
||||
import React from "react";
|
||||
|
||||
type IndicatorsProps = {
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import CommandLink from '../CommandLink';
|
||||
import CommandLink from '../../core/components/CommandLink';
|
||||
import './WhatsNewResultView.css';
|
||||
|
||||
function WhatsnewResultView() {
|
||||
8
src/shell/interfaces.ts
Normal file
8
src/shell/interfaces.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import AppState from "./AppState";
|
||||
import { CmdShell } from "./cmd";
|
||||
|
||||
export type Env = 'prod' | 'stage';
|
||||
|
||||
export type AppModule = {
|
||||
setup: (appState: AppState, cmd: CmdShell) => void;
|
||||
};
|
||||
36
src/shell/module.tsx
Normal file
36
src/shell/module.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import uuid from 'uuid';
|
||||
import AppState from './AppState';
|
||||
import { CmdShell, CommandInput } from './cmd';
|
||||
import AboutResultView from './components/AboutResultView';
|
||||
import ErrorResultView from './components/ErrorResultView';
|
||||
import HelpResultView from './components/HelpResultView';
|
||||
import TextResultView from './components/TextResultView';
|
||||
import WhatsnewResultView from './components/WhatsNewResultView';
|
||||
|
||||
const shellModule = {
|
||||
setup: function(appState: AppState, cmd: CmdShell) {
|
||||
|
||||
cmd.debugMode = appState.debugMode;
|
||||
appState.onChange(() => cmd.debugMode = appState.debugMode);
|
||||
|
||||
cmd.command("help", (c: CommandInput) => appState.addCommandResult(c.input, <HelpResultView />));
|
||||
cmd.command("clear", () => appState.clearCommandResults());
|
||||
cmd.command("em", () => appState.toggleEmphasizeBytes());
|
||||
cmd.command("dark", () => appState.setUiTheme('dark'));
|
||||
cmd.command("light", () => appState.setUiTheme('light'));
|
||||
cmd.command("midnight", () => appState.setUiTheme('midnight'));
|
||||
cmd.command("about", (c: CommandInput) => appState.addCommandResult(c.input, <AboutResultView />));
|
||||
cmd.command("whatsnew", (c: CommandInput) => appState.addCommandResult(c.input, <WhatsnewResultView />));
|
||||
cmd.command("guid", (c: CommandInput) => appState.addCommandResult(c.input, <TextResultView text={uuid()} />));
|
||||
cmd.command("-notrack", () => {});
|
||||
cmd.command("-debug", (c: CommandInput) => {
|
||||
appState.toggleDebugMode();
|
||||
appState.addCommandResult(c.input, <TextResultView text={`Debug Mode: ${appState.debugMode}`}/>);
|
||||
});
|
||||
|
||||
cmd.onError((input: string, err: Error) => appState.addCommandResult(input, <ErrorResultView errorMessage={err.toString()} />));
|
||||
}
|
||||
}
|
||||
|
||||
export default shellModule;
|
||||
62
src/shell/startup.ts
Normal file
62
src/shell/startup.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import log from 'loglevel';
|
||||
import hash from '../core/hash';
|
||||
import AppState from './AppState';
|
||||
import { Env } from './interfaces';
|
||||
import appStateStore from './appStateStore';
|
||||
|
||||
export type StartupAppData = {
|
||||
appState: AppState,
|
||||
startupCommands: string[]
|
||||
}
|
||||
|
||||
function bootstrapAppData() : StartupAppData {
|
||||
const env = window.location.host === "bitwisecmd.com" ? 'prod' : 'stage';
|
||||
|
||||
setupLogger(env);
|
||||
|
||||
const appState = createAppState(env);
|
||||
const startupCommands = getStartupCommands(appState);
|
||||
|
||||
return {
|
||||
appState,
|
||||
startupCommands
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function createAppState(env:string) {
|
||||
var stateData = appStateStore.getPersistedData();
|
||||
const appState = new AppState(stateData, env);
|
||||
appStateStore.watch(appState);
|
||||
log.debug("appState initialized", appState);
|
||||
return appState;
|
||||
}
|
||||
|
||||
function getStartupCommands(appState : AppState) : string[] {
|
||||
var hashArgs = hash.getArgs(window.location.hash);
|
||||
|
||||
var startupCommands = ['help', '127.0.0.1 192.168.0.0/8', '1|2&6','4 0b1000000 0x80'];
|
||||
|
||||
if(appState.wasOldVersion) {
|
||||
startupCommands = ["whatsnew"];
|
||||
}
|
||||
|
||||
if(hashArgs.length > 0) {
|
||||
startupCommands = hashArgs;
|
||||
}
|
||||
|
||||
log.debug('Executing startup commands', startupCommands);
|
||||
|
||||
return startupCommands;
|
||||
}
|
||||
|
||||
function setupLogger(env: Env) {
|
||||
if(env != 'prod'){
|
||||
log.setLevel("debug");
|
||||
log.debug(`Log level is set to debug. Env: ${env}`)
|
||||
} else {
|
||||
log.setLevel("warn");
|
||||
}
|
||||
}
|
||||
|
||||
export default bootstrapAppData;
|
||||
Reference in New Issue
Block a user