Kuker :heart: React (Supports only React 14.x.x. Sorry!), Angular, Vue & Vuex, Redux, redux-saga, HTML, Stent, Machina.js, MobX
You want your framework listed here? Check out the Emitters section and learn how to integrate it with Kuker.
If you build software you probably know that debugging what you just wrote is really important. Without seeing how your code works on a lower level you can't say that something is done. Finding and fixing bugs is also important. And without a proper tool it becomes difficult and time consuming. Kuker is here to help by improving your workflow.
I'm working with React, Redux and redux-saga last years and they seem to have pretty active community. Community that built awesome tools which improve the developer experience. One of these tools is Redux-DevTools. I got lots of ideas from there and my goal in the beginning was to write (for fun) a clone with a little bit more features. Stuff which I wanted to see. However, later I realized that this may be used out of Redux context and basically support every library or framework. It answers of two important questions.
The extension answers on these two questions. We have two panels. The one on the left shows a list of all the actions/events in your application while the one on the right displays the state after each one of them.
The following screenshot demonstrate how the extension works with React emitter and Redux emitter plugged in:
To make the extension work you have to instrument your application. You have to add an emitter which listens for actions/events on your side and sends them to Kuker.
yarn add kuker-emitters
or npm install kuker-emitters
. There're also standalone versions in here. You may grab the file, include it in your page and you'll a global like ReduxEmitter
, ReduxSagaEmitter
or ReactEmitter
.
import { ReactEmitter } from 'kuker-emitters';
ReactEmitter();
import { AngularEmitter } from 'kuker-emitters';
AngularEmitter();
AngularEmitter
accepts a single parameter options
which by default is equal to { rootSelector: 'app-root' }
. The root element in a Angular app is usually app-root
(at least in the latest versions). If it happens to be a different one set the proper selector. Also you should compile your app in a development mode. Otherwise ng.probe
is not available and the emitter can not send events.
import { VueEmitter } from 'kuker-emitters';
VueEmitter();
The same VueEmitter
works for Vuex too.
import { createStore, applyMiddleware } from 'redux';
import { ReduxEmitter } from 'kuker-emitters';
const middleware = ReduxEmitter();
const store = createStore(<reducer>, applyMiddleware(middleware));
import { createStore, applyMiddleware } from 'redux';
import { ReduxSagaEmitter } from 'kuker-emitters';
import createSagaMiddleware from 'redux-saga';
const emitter = ReduxSagaEmitter();
const sagaMiddleware = createSagaMiddleware({ sagaMonitor: emitter.sagaMonitor });
const store = createStore(<reducer>, applyMiddleware(sagaMiddleware));
// This bit is really important.
// Without it you won't get the current state of the app with every event.
emitter.setStore(store);
sagaMiddleware.run(rootSaga)
import { HTMLEmitter } from 'kuker-emitters';
HTMLEmitter();
import { Machine } from 'stent';
import { StentEmitter } from 'kuker-emitters';
Machine.addMiddleware(StentEmitter());
import machina from 'machina';
import { MachinaEmitter } from 'kuker-emitters';
const machine = new machina.Fsm({...});
MachinaEmitter(machine);
import { MobXEmitter } from 'kuker-emitters';
import { spy, observable, action } from 'mobx';
class Person {
@observable age = 33;
@action newYear() {
this.age += 1;
}
}
const person = new Person();
MobXEmitter(spy, [ person ]);
import { BaseEmitter } from 'kuker-emitters';
const emit = BaseEmitter();
emit({
type: 'adding money to my account',
label: 'hello',
state: { bank: { money: 100 } },
icon: 'fa-money',
color: '#bada55'
});
Of course you don't have to use any of these emitters to enjoy Kuker. You may send a message on your own using the postMessage
API:
window.postMessage({
kuker: true,
type: 'adding money to my account',
origin: 'something',
label: 'hello',
time: (new Date()).getTime(),
state: { bank: { money: 100 } },
icon: 'fa-money',
color: '#bada55'
}, '*');
The result of this postMessage
call is as follows:
The only required properties are type
and kuker: true
. You may skip the others if you want. icon
is one of the FontAwesome icons.
The problem of doing it alone is that you have to take care for a two things:
window.postMessage
is available (does not exist in node environment).All these three issues are solved by using the BaseEmitter.
I'll be more then happy to see you contributing to kuker-emitters. There're also utility functions for calling postMessage
.
In the beginning there was a guard in the emitters that makes sure that events are sent only if the extension is installed. However, this technique involves the content script of the extension to inject some stuff on the page which was fragile and buggy. I decided to kill that feature until I find a better way to handle it. So, for the time being you have to guard the emitters.
Once you load the app the integrated emitters start calling window.postMessage
. The content script is listening for this messages and via the chrome.runtime
API sends them to the DevTools panel. The rest is just a small React app that displays them.