Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d910a0f75 | ||
|
|
ab74f6426e | ||
|
|
390bb8ff67 | ||
|
|
fcd108f9e7 | ||
|
|
dd2c6ee3d2 | ||
|
|
9917425cc8 | ||
|
|
3f54ca11a1 | ||
|
|
e059f800d6 | ||
|
|
f2dec10c05 | ||
|
|
d8117eac7d | ||
|
|
354514818c | ||
|
|
4ac814be93 | ||
|
|
2f7387a67f | ||
|
|
1cf779c5a6 | ||
|
|
64c9a75d92 | ||
|
|
5a8c4e6a9b | ||
|
|
2fd728b5e8 | ||
|
|
9bda1672d5 | ||
|
|
101eade38f | ||
|
|
6a1c8bcd75 | ||
|
|
c49a09e721 | ||
|
|
d526ded04b | ||
|
|
06344bee72 | ||
|
|
897dcb8c3b |
24
README.md
24
README.md
@@ -40,15 +40,19 @@ Check out the example of [**standalone version running here**](https://codecrumb
|
||||
2) Run ```codecrumbs -d project-src-dir -e project-src-dir/index.js```. Change parameters to match your project:```-d``` is *directory with source code*, ```-e``` is *entry point file* .
|
||||
3) Go to [http://localhost:2018](http://localhost:2018/#) in the browser to check it out.
|
||||
|
||||
### CLI
|
||||
Parameter | Description | Example
|
||||
--- | --- | ---
|
||||
```-d```, ```--dir``` | Relative path to project source code directory | ```-d src```
|
||||
```-e```, ```--entry``` | Relative path to project source entry point file (must be inside ```dir```) | ```-e src/app.js```
|
||||
```-x```, ```--excludeDir``` | Relative path(or paths separated by ```,```) to directories for exclusion | ```-x src/doc,src/thirdparty```
|
||||
```-i```, ```--ideCmd``` | command to open file in IDE from bash (default 'webstorm') | ```-i code```
|
||||
```-p```, ```--port``` | Port for Codecrumbs client (optional, default *2018*) | ```-p 2019```
|
||||
```-n```, ```--projectName``` | Project name alias (optional, default same as ```-d``` value) | ```-n my-hello-world```
|
||||
### Configuration
|
||||
Run codecrumbs with CLI params or specify static config file `codecrumbs.config.js` (see example [here](/example-project/codecrumbs.config.js))
|
||||
|
||||
CLI | Config file | Description | Example
|
||||
--- | --- | --- | ---
|
||||
```d``` | ```projectDir``` | Relative path to project source code directory | ```-d src```
|
||||
```e``` | ```entryPoint``` | Relative path to project source entry point file (must be inside ```dir```) | ```-e src/app.js```
|
||||
```x``` | ```excludeDir``` | Relative path(or paths separated by ```,```) to directories for exclusion | ```-x src/doc,src/thirdparty```
|
||||
```i``` | ```ideCmd``` | command to open file in IDE from bash (default 'webstorm') | ```-i code```
|
||||
```p``` | ```clientPort``` | Port for Codecrumbs client (optional, default *2018*) | ```-p 2019```
|
||||
```n``` | ```projectNameAlias``` | Project name alias (optional, default same as ```-d``` value) | ```-n my-hello-world```
|
||||
```C``` | - | Path to codecrumbs.config.js (optional, by default will try to find the file in PWD) | ```-C config/codecrumbs.config.js```
|
||||
```D``` | ```debugModeEnabled``` | Enable debug mode for logs (optional, default is ```false```) | ```-D```
|
||||
|
||||
## Features
|
||||
### Breadcrumbs and trails
|
||||
@@ -76,6 +80,8 @@ Example | Description | Use case
|
||||
|
||||
> Note: current version supports single line comments only.
|
||||
|
||||
> Hint: you can use trail id without step number (e.g. ```//cc:groupname#;test```) just to group breadcrumbs, you always can add step numbers later when you know the correct order.
|
||||
|
||||
### Multi-codebase integration
|
||||
You might be interested to study connections between several codebases (sub-modules), codecrumbs supports that.
|
||||
Simply start codecrumbs multiple times (once for each codebase), it all **will be synced in one picture** inside the browser tab. To control a diagram UI - select it by clicking on it.
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const path = require('path');
|
||||
const program = require('commander');
|
||||
const colors = require('colors');
|
||||
const _ = require('lodash');
|
||||
|
||||
const showUpdatesInfo = require('./updatesInfo');
|
||||
const server = require('../src/server');
|
||||
|
||||
showUpdatesInfo();
|
||||
|
||||
program
|
||||
.option('-e, --entry [entryFile]', 'Specify path to entry point file. E.g. `src/app.js`')
|
||||
.option('-e, --entry [entryPoint]', 'Specify path to entry point file. E.g. `src/app.js`')
|
||||
.option('-d, --dir [projectDir]', 'Specify path to project source code directory. E.g. `src`', '')
|
||||
.option(
|
||||
'-w, --webpack [webpackConfigFile]',
|
||||
@@ -20,27 +25,33 @@ program
|
||||
.option('-i, --ideCmd [ideCmd]', 'IDE command to open file')
|
||||
.option('-x, --excludeDir [excludeDirectories]', 'Exclude directories')
|
||||
.option('-n, --projectName [projectNameAlias]', 'Project name alias')
|
||||
.option('-C, --configFile [pathToConfigFile]', 'Path to codecrumbs.config.js')
|
||||
.option('-D, --debugModeEnabled [debugModeEnabled]', 'Enable debug mode for logs.')
|
||||
.parse(process.argv);
|
||||
|
||||
if (!program.entry || !program.dir) {
|
||||
const pathToConfigFile = program.configFile || 'codecrumbs.config.js';
|
||||
const configFileExists = server.checkIfPathExists(pathToConfigFile);
|
||||
if ((!program.entry || !program.dir) && !configFileExists) {
|
||||
console.log(
|
||||
colors.magenta(
|
||||
'Please specify `entry` and `dir` params. E.g. `codecrumbs -e src/app.js -d src`'
|
||||
'Please specify `entryPoint` and `projectDir` params (e.g. `codecrumbs -e src/app.js -d src`). Or use `-C codecrumbs.config.js` instead.'
|
||||
)
|
||||
);
|
||||
process.exit();
|
||||
}
|
||||
|
||||
server.setup(
|
||||
{
|
||||
projectNameAlias: program.projectName,
|
||||
entryPoint: program.entry,
|
||||
projectDir: program.dir,
|
||||
webpackConfigPath: program.webpack,
|
||||
tsConfigPath: program.tsconfig,
|
||||
clientPort: program.port,
|
||||
excludeDir: program.excludeDir,
|
||||
ideCmd: program.ideCmd
|
||||
},
|
||||
{ isDev: false }
|
||||
);
|
||||
const configFromFile = configFileExists ? require(path.resolve(pathToConfigFile)) : {};
|
||||
|
||||
const configFromCLI = {
|
||||
projectNameAlias: program.projectName,
|
||||
entryPoint: program.entry,
|
||||
projectDir: program.dir,
|
||||
webpackConfigPath: program.webpack,
|
||||
tsConfigPath: program.tsconfig,
|
||||
clientPort: program.port,
|
||||
excludeDir: program.excludeDir,
|
||||
ideCmd: program.ideCmd,
|
||||
debugModeEnabled: program.debugModeEnabled
|
||||
};
|
||||
|
||||
server.setup(_.merge(configFromCLI, configFromFile), { isDev: false });
|
||||
|
||||
20
cli/updatesInfo.js
Normal file
20
cli/updatesInfo.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const colors = require('colors');
|
||||
const exec = require('child_process').exec;
|
||||
|
||||
module.exports = () => {
|
||||
try {
|
||||
exec('npm outdated codecrumbs').stdout.on('data', function(data) {
|
||||
const list = data
|
||||
.split(' ')
|
||||
.filter(v => !!v)
|
||||
.map(v => v.trim());
|
||||
|
||||
const latestVersion = list[list.length - 2];
|
||||
console.log(
|
||||
colors.cyan.underline(
|
||||
`There is new version of codecrumbs (${latestVersion}) available! Please update to have all latest features and improvements!`
|
||||
)
|
||||
);
|
||||
});
|
||||
} catch (e) {}
|
||||
};
|
||||
7
example-project/codecrumbs.config.js
Normal file
7
example-project/codecrumbs.config.js
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
entryPoint: 'example-project/src-client/index.js',
|
||||
projectDir: 'example-project/src-client',
|
||||
clientPort: 1234,
|
||||
projectNameAlias: 'example-project-for-client',
|
||||
debugModeEnabled: true
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "codecrumbs",
|
||||
"version": "1.6.13",
|
||||
"version": "1.7.0",
|
||||
"author": "Bohdan Liashenko",
|
||||
"license": "BSD-3-Clause",
|
||||
"repository": {
|
||||
@@ -13,6 +13,7 @@
|
||||
"server:two": "node src/index.dev.js two",
|
||||
"client-dev": "cd src/public && webpack --config webpack.dev.js --progress --colors --watch --env dev",
|
||||
"server-dev": "nodemon src/index.dev.js",
|
||||
"server:cli": "node cli/index.cli.js -e example-project/src-client/index.js -d example-project/src-client/",
|
||||
"server-debug": "nodemon --inspect src/index.dev.js",
|
||||
"clean": "rm -rf build",
|
||||
"babel-compile-standalone": "babel src/public/js -d build --config-file ./src/public/babel.config.js --copy-files",
|
||||
|
||||
@@ -5,7 +5,8 @@ const namespaceOne = {
|
||||
projectDir: `example-project/src-client`,
|
||||
entryPoint: `example-project/src-client/index.js`,
|
||||
webpackConfigPath: `example-project/webpack.config.js`,
|
||||
clientPort: 2018
|
||||
clientPort: 2018,
|
||||
debugModeEnabled: true
|
||||
};
|
||||
|
||||
const namespaceTwo = {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.MainLoader {
|
||||
|
||||
@@ -15,11 +15,21 @@ import {
|
||||
getNamespacesList
|
||||
} from '../../../core/dataBus/selectors';
|
||||
import { getCheckedState, getValuesState } from '../../../core/controlsBus/selectors';
|
||||
import { selectDependencyEdge, selectCcFlowEdge } from '../../../core/dataBus/actions';
|
||||
import {
|
||||
selectDependencyEdge,
|
||||
selectCcFlowEdge,
|
||||
saveTreeDiagramContentId
|
||||
} from '../../../core/dataBus/actions';
|
||||
import { setActiveNamespace } from '../../../core/namespaceIntegration/actions';
|
||||
import { gatherFlowStepsData, getMaxWidthForNs } from './Tree/CodeCrumbs/helpers';
|
||||
|
||||
class TreeDiagram extends React.Component {
|
||||
componentDidUpdate(prevProps) {
|
||||
if (!prevProps.layoutSize && this.props.layoutSize) {
|
||||
this.props.saveContentId(this.treeDiagramContent.getAttribute('id'));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
// TODO: fix diagramZoom
|
||||
const {
|
||||
@@ -60,35 +70,41 @@ class TreeDiagram extends React.Component {
|
||||
{projectName}
|
||||
</p>
|
||||
) : null}
|
||||
<svg
|
||||
width={maxWidth || width}
|
||||
height={height}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
shapeRendering="optimizeSpeed"
|
||||
<div
|
||||
id={`TreeDiagram-${namespace}-content`}
|
||||
className={'content'}
|
||||
ref={el => (this.treeDiagramContent = el)}
|
||||
>
|
||||
{sourceLayoutTree && (
|
||||
<React.Fragment>
|
||||
<UnderLayer width={maxWidth || width} height={height} onClick={onUnderLayerClick} />
|
||||
<SourceTree
|
||||
namespace={namespace}
|
||||
shiftToCenterPoint={shiftToCenterPoint}
|
||||
areaHeight={height}
|
||||
sortedFlowSteps={sortedFlowSteps}
|
||||
involvedNsData={involvedNsData}
|
||||
ccShiftIndexMap={ccShiftIndexMap}
|
||||
/>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</svg>
|
||||
{codeCrumbsDiagramOn ? (
|
||||
<CodeCrumbsExtraInfo
|
||||
namespace={namespace}
|
||||
shiftToCenterPoint={shiftToCenterPoint}
|
||||
ccShiftIndexMap={ccShiftIndexMap}
|
||||
sortedFlowSteps={sortedFlowSteps}
|
||||
flowSteps={flowSteps}
|
||||
/>
|
||||
) : null}
|
||||
<svg
|
||||
width={maxWidth || width}
|
||||
height={height}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
shapeRendering="optimizeSpeed"
|
||||
>
|
||||
{sourceLayoutTree && (
|
||||
<React.Fragment>
|
||||
<UnderLayer width={maxWidth || width} height={height} onClick={onUnderLayerClick} />
|
||||
<SourceTree
|
||||
namespace={namespace}
|
||||
shiftToCenterPoint={shiftToCenterPoint}
|
||||
areaHeight={height}
|
||||
sortedFlowSteps={sortedFlowSteps}
|
||||
involvedNsData={involvedNsData}
|
||||
ccShiftIndexMap={ccShiftIndexMap}
|
||||
/>
|
||||
</React.Fragment>
|
||||
)}
|
||||
</svg>
|
||||
{codeCrumbsDiagramOn ? (
|
||||
<CodeCrumbsExtraInfo
|
||||
namespace={namespace}
|
||||
shiftToCenterPoint={shiftToCenterPoint}
|
||||
ccShiftIndexMap={ccShiftIndexMap}
|
||||
sortedFlowSteps={sortedFlowSteps}
|
||||
flowSteps={flowSteps}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -149,7 +165,8 @@ const mapDispatchToProps = (dispatch, props) => {
|
||||
dispatch(setActiveNamespace(namespace));
|
||||
dispatch(selectDependencyEdge(undefined, namespace));
|
||||
dispatch(selectCcFlowEdge(undefined, namespace));
|
||||
}
|
||||
},
|
||||
saveContentId: ref => dispatch(saveTreeDiagramContentId(ref, namespace))
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
display: block;
|
||||
.content {
|
||||
svg {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,6 +340,12 @@ export const setPredefinedState = predefinedState => dispatch => {
|
||||
});
|
||||
};
|
||||
|
||||
export const saveTreeDiagramContentId = (payload, namespace) => ({
|
||||
type: ACTIONS.SAVE_TREE_DIAGRAM_CONTENT_ID,
|
||||
payload,
|
||||
namespace
|
||||
});
|
||||
|
||||
export const setFullState = payload => ({
|
||||
type: ACTIONS.SET_FULL_STATE,
|
||||
payload
|
||||
|
||||
@@ -16,5 +16,6 @@ export const ACTIONS = {
|
||||
SET_DEPENDENCIES_ENTRY_POINT: 'DATA_BUS.SET_DEPENDENCIES_ENTRY_POINT',
|
||||
SELECT_DEPENDENCY_EDGE: 'DATA_BUS.SELECT_DEPENDENCY_EDGE',
|
||||
SELECT_CC_FLOW_EDGE: 'DATA_BUS.SELECT_CC_FLOW_EDGE',
|
||||
UPDATE_FILES: 'DATA_BUS.UPDATE_FILES'
|
||||
UPDATE_FILES: 'DATA_BUS.UPDATE_FILES',
|
||||
SAVE_TREE_DIAGRAM_CONTENT_ID: 'DATA_BUS.SAVE_TREE_DIAGRAM_CONTENT_ID'
|
||||
};
|
||||
|
||||
@@ -195,6 +195,11 @@ export default (state = DefaultState, action) => {
|
||||
}
|
||||
});
|
||||
|
||||
case ACTIONS.SAVE_TREE_DIAGRAM_CONTENT_ID:
|
||||
return mergeState({
|
||||
treeDiagramContentId: action.payload
|
||||
});
|
||||
|
||||
case ACTIONS.SET_FULL_STATE:
|
||||
return {
|
||||
...state,
|
||||
|
||||
@@ -13,6 +13,11 @@ export const getProjectMetadata = createSelector([getNamespaceState], namespaceS
|
||||
return { projectName, language, platformPathSeparator, fullFeaturesSupport };
|
||||
});
|
||||
|
||||
export const getTreeDiagramContentId = createSelector([getNamespaceState], namespaceState => {
|
||||
const { treeDiagramContentId } = namespaceState;
|
||||
return { id: treeDiagramContentId };
|
||||
});
|
||||
|
||||
export const getSource = createSelector([getNamespaceState], namespaceState => {
|
||||
const { sourceTree, filesMap, foldersMap } = namespaceState;
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ export const calculateLayoutProps = (list, padding = 120) => {
|
||||
const width = Math.round(Math.abs(maxX + maxCcWidth) + Math.abs(minX) + 2 * padding);
|
||||
|
||||
return {
|
||||
xShift: padding / 4,
|
||||
xShift: 5,
|
||||
width,
|
||||
height,
|
||||
yShift,
|
||||
|
||||
@@ -9,13 +9,13 @@ import dataBus from '../dataBus/reducer';
|
||||
import namespaceIntegration from '../namespaceIntegration/reducer';
|
||||
import rootSaga from './sagas';
|
||||
|
||||
export default ({ extraReducers } = {}) => {
|
||||
export default ({ extraReducers = {}, extraPersistWhiteList = [] } = {}) => {
|
||||
const sagaMiddleware = createSagaMiddleware();
|
||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
||||
|
||||
const persistConfig = {
|
||||
key: 'codecrumbs-config-storage',
|
||||
whitelist: ['controlsBus'],
|
||||
whitelist: ['controlsBus', ...extraPersistWhiteList],
|
||||
storage
|
||||
};
|
||||
|
||||
|
||||
@@ -10,9 +10,6 @@ const mediator = require('./mediator');
|
||||
const sourceWatcher = require('./source-watcher');
|
||||
|
||||
const setup = (options, devOptions) => {
|
||||
logger.fun(`>\n> Codecrumbs magic begins!\n>`);
|
||||
logger.info(`> started with options: ${JSON.stringify(options)}`);
|
||||
|
||||
const {
|
||||
projectNameAlias,
|
||||
projectDir,
|
||||
@@ -21,9 +18,15 @@ const setup = (options, devOptions) => {
|
||||
tsConfigPath,
|
||||
clientPort,
|
||||
excludeDir,
|
||||
ideCmd
|
||||
ideCmd,
|
||||
debugModeEnabled
|
||||
} = options;
|
||||
|
||||
logger.setDebugModeEnabled(debugModeEnabled);
|
||||
|
||||
logger.fun(`>\n> Codecrumbs magic begins!\n>`);
|
||||
logger.info(`> started with options: ${JSON.stringify(options)}`);
|
||||
|
||||
const PORT_IN_USE = 'open';
|
||||
const HOST = '127.0.0.1';
|
||||
|
||||
@@ -94,11 +97,11 @@ const alignPlatformPath = (p = '') =>
|
||||
|
||||
const validateProjectPath = (pDir, ePoint) => {
|
||||
const paths = [];
|
||||
if (!fs.existsSync(alignPlatformPath(pDir))) {
|
||||
if (!checkIfPathExists(pDir)) {
|
||||
paths.push(pDir);
|
||||
}
|
||||
|
||||
if (!fs.existsSync(alignPlatformPath(ePoint))) {
|
||||
if (!checkIfPathExists(ePoint)) {
|
||||
paths.push(ePoint);
|
||||
}
|
||||
|
||||
@@ -110,6 +113,9 @@ const validateProjectPath = (pDir, ePoint) => {
|
||||
}
|
||||
};
|
||||
|
||||
const checkIfPathExists = path => fs.existsSync(alignPlatformPath(path));
|
||||
|
||||
module.exports = {
|
||||
checkIfPathExists,
|
||||
setup
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const chalk = require('chalk');
|
||||
|
||||
const logAdapter = msg => console.log(msg);
|
||||
let isDebugModeEnabled = false;
|
||||
const logAdapter = (msg, force) => (isDebugModeEnabled || force) && console.log(msg);
|
||||
|
||||
module.exports = {
|
||||
getText: e => {
|
||||
@@ -13,6 +14,7 @@ module.exports = {
|
||||
log: (...args) => logAdapter(chalk.blue.apply(chalk, args)),
|
||||
info: (...args) => logAdapter(chalk.green.apply(chalk, args)),
|
||||
warn: (...args) => logAdapter(chalk.yellow.apply(chalk, args)),
|
||||
error: (...args) => logAdapter(chalk.red.apply(chalk, args)),
|
||||
fun: (...args) => logAdapter(chalk.keyword('purple').apply(chalk, args))
|
||||
error: (...args) => logAdapter(chalk.red.apply(chalk, args), true),
|
||||
fun: (...args) => logAdapter(chalk.keyword('purple').apply(chalk, args), true),
|
||||
setDebugModeEnabled: (debugModeEnabled) => isDebugModeEnabled = debugModeEnabled
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user