mirror of
https://github.com/urbit/shrub.git
synced 2025-01-01 17:16:47 +03:00
dbug: allow custom state queries
Try to give state version number on first load. Run custom queries on demand, similar to +dbug [%state 'whatever'].
This commit is contained in:
parent
15e3ea6940
commit
da4274d490
@ -153,57 +153,81 @@
|
||||
(as-octt:mimes (en-json u.json))
|
||||
=, enjs:format
|
||||
?+ site ~
|
||||
:: /app.json: {appname: running, ...}
|
||||
:: /apps.json: {appname: running?}
|
||||
::
|
||||
[%app ~]
|
||||
[%apps ~]
|
||||
%- some
|
||||
%- pairs
|
||||
%+ turn all:apps
|
||||
|= app=term
|
||||
[app b+(running:apps app)]
|
||||
::
|
||||
:: /app/[appname].json: {state: }
|
||||
:: /app/[appname]...
|
||||
::
|
||||
[%app @ ~]
|
||||
[%app @ *]
|
||||
=* app i.t.site
|
||||
::TODO ?. (dbugable:apps app) ~
|
||||
%- some
|
||||
%- pairs
|
||||
:~ :- 'state'
|
||||
(tank (sell (state:apps app)))
|
||||
=/ rest=^path t.t.site
|
||||
?+ rest ~
|
||||
:: /app/[appname].json: {state: }
|
||||
::
|
||||
:- 'subscriptions'
|
||||
%- pairs
|
||||
=+ (subscriptions:apps app)
|
||||
|^ ~['in'^(incoming in) 'out'^(outgoing out)]
|
||||
~
|
||||
%- some
|
||||
%- pairs
|
||||
:~ :- 'simpleState'
|
||||
%- tank
|
||||
=; head=(unit ^tank)
|
||||
(fall head leaf+"unversioned")
|
||||
:: try to print the state version
|
||||
::
|
||||
=/ version=(unit vase)
|
||||
(slew 2 (state:apps app))
|
||||
?~ version ~
|
||||
?. ?=(%atom -.p.u.version) ~
|
||||
`(sell u.version)
|
||||
::
|
||||
++ incoming
|
||||
|= =bitt:gall
|
||||
^- json
|
||||
:- %a
|
||||
%+ turn ~(tap by bitt)
|
||||
|= [d=duct [s=^ship p=^path]]
|
||||
:- 'subscriptions'
|
||||
%- pairs
|
||||
~! (ship s)
|
||||
:~ 'duct'^a+(turn d path)
|
||||
'ship'^(ship s)
|
||||
'path'^(path p)
|
||||
==
|
||||
::
|
||||
++ outgoing
|
||||
|= =boat:gall
|
||||
^- json
|
||||
:- %a
|
||||
%+ turn ~(tap by boat)
|
||||
|= [[w=wire s=^ship t=term] [a=? p=^path]]
|
||||
%- pairs
|
||||
:~ 'wire'^(path w)
|
||||
'ship'^(ship s)
|
||||
'app'^s+t
|
||||
'acked'^b+a
|
||||
'path'^(path p)
|
||||
==
|
||||
--
|
||||
=+ (subscriptions:apps app)
|
||||
|^ ~['in'^(incoming in) 'out'^(outgoing out)]
|
||||
::
|
||||
++ incoming
|
||||
|= =bitt:gall
|
||||
^- json
|
||||
:- %a
|
||||
%+ turn ~(tap by bitt)
|
||||
|= [d=duct [s=^ship p=^path]]
|
||||
%- pairs
|
||||
:~ 'duct'^a+(turn d path)
|
||||
'ship'^(ship s)
|
||||
'path'^(path p)
|
||||
==
|
||||
::
|
||||
++ outgoing
|
||||
|= =boat:gall
|
||||
^- json
|
||||
:- %a
|
||||
%+ turn ~(tap by boat)
|
||||
|= [[w=wire s=^ship t=term] [a=? p=^path]]
|
||||
%- pairs
|
||||
:~ 'wire'^(path w)
|
||||
'ship'^(ship s)
|
||||
'app'^s+t
|
||||
'acked'^b+a
|
||||
'path'^(path p)
|
||||
==
|
||||
--
|
||||
==
|
||||
::
|
||||
:: /app/[appname]/state.json
|
||||
:: /app/[appname]/state/[query].json
|
||||
::
|
||||
[%state ?(~ [@ ~])]
|
||||
%- some
|
||||
=- (pairs 'state'^(tank -) ~)
|
||||
%+ state-at:apps app
|
||||
?~ t.rest ~
|
||||
(slaw %t i.t.rest)
|
||||
==
|
||||
::
|
||||
:: /spider.json
|
||||
@ -335,17 +359,33 @@
|
||||
::
|
||||
++ state
|
||||
|= app=term
|
||||
(scry-dbug vase app /dbug/state)
|
||||
^- vase
|
||||
(scry-dbug vase app /state)
|
||||
::
|
||||
++ state-at
|
||||
|= [app=term what=(unit @t)]
|
||||
^- tank
|
||||
=/ state=vase (state app)
|
||||
?~ what (sell state)
|
||||
=/ result=(each vase tang)
|
||||
%- mule |.
|
||||
%+ slap
|
||||
(slop state !>([bowl=bowl ..zuse]))
|
||||
(ream u.what)
|
||||
?- -.result
|
||||
%& (sell p.result)
|
||||
%| (head p.result)
|
||||
==
|
||||
::
|
||||
++ subscriptions
|
||||
=, gall
|
||||
|= app=term
|
||||
^- [out=boat in=bitt]
|
||||
(scry-dbug ,[boat bitt] app /dbug/subscriptions)
|
||||
(scry-dbug ,[boat bitt] app /subscriptions)
|
||||
::
|
||||
++ scry-dbug
|
||||
|* [=mold app=term =path]
|
||||
(scry mold %gx app (snoc `^path`path %noun))
|
||||
(scry mold %gx app (snoc `^path`[%dbug path] %noun))
|
||||
::
|
||||
::TODO but why? we can't tell if it's on or not
|
||||
++ poke-verb-toggle
|
||||
|
@ -3,6 +3,7 @@ import ReactDOM from 'react-dom';
|
||||
import _ from 'lodash';
|
||||
import { store } from '/store';
|
||||
import moment from 'moment';
|
||||
import { stringToTa } from './lib/util';
|
||||
|
||||
|
||||
class UrbitApi {
|
||||
@ -113,9 +114,7 @@ class UrbitApi {
|
||||
// apps
|
||||
|
||||
getApps() {
|
||||
//TODO onfail render "failed to fetch apps"
|
||||
//TODO generic "fail" local event that prints to status bar?
|
||||
this.getJson('/app',
|
||||
this.getJson('/apps',
|
||||
this.wrapLocal('apps'),
|
||||
this.showStatus('error fetching apps')
|
||||
);
|
||||
@ -132,6 +131,19 @@ class UrbitApi {
|
||||
);
|
||||
}
|
||||
|
||||
getAppState(app, state = '') {
|
||||
if (state !== '') {
|
||||
state = '/' + stringToTa(state)
|
||||
}
|
||||
this.getJson('/app/'+app+'/state'+state, (data) => {
|
||||
data.app = app;
|
||||
return this.wrapLocal('appState')(data);
|
||||
},
|
||||
() => { // on fail
|
||||
store.handleEvent({data: { local: { 'appFailed': app } }});
|
||||
});
|
||||
}
|
||||
|
||||
// spider
|
||||
|
||||
getThreads() {
|
||||
|
@ -30,3 +30,41 @@ export function msToDa(ms, mil) {
|
||||
export function renderDuct(duct) {
|
||||
return duct.reduce((a, b) => a + b + ' ', '');
|
||||
}
|
||||
|
||||
// encode the string into @ta-safe format, using logic from +wood.
|
||||
// for example, 'some Chars!' becomes '~.some.~43.hars~21.'
|
||||
// this is equivalent to (scot %t string)
|
||||
//
|
||||
export function stringToTa(string) {
|
||||
let out = '';
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
const char = string[i];
|
||||
let add = '';
|
||||
switch (char) {
|
||||
case ' ':
|
||||
add = '.';
|
||||
break;
|
||||
case '.':
|
||||
add = '~.';
|
||||
break;
|
||||
case '~':
|
||||
add = '~~';
|
||||
break;
|
||||
default:
|
||||
const charCode = string.charCodeAt(i);
|
||||
if (
|
||||
(charCode >= 97 && charCode <= 122) || // a-z
|
||||
(charCode >= 48 && charCode <= 57) || // 0-9
|
||||
char === '-'
|
||||
) {
|
||||
add = char;
|
||||
} else {
|
||||
// TODO behavior for unicode doesn't match +wood's,
|
||||
// but we can probably get away with that for now.
|
||||
add = '~' + charCode.toString(16) + '.';
|
||||
}
|
||||
}
|
||||
out = out + add;
|
||||
}
|
||||
return '~~' + out;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ export class LocalReducer {
|
||||
//
|
||||
this.apps(data, state);
|
||||
this.app(data, state);
|
||||
this.appState(data, state);
|
||||
this.appFailed(data, state);
|
||||
this.verbResult(data, state);
|
||||
this.verbStatus(data, state);
|
||||
@ -48,10 +49,18 @@ export class LocalReducer {
|
||||
app(obj, state) {
|
||||
const data = _.get(obj, 'app', false);
|
||||
if (data) {
|
||||
if (state.apps[data.app]) data.state = state.apps[data.app].state;
|
||||
state.apps[data.app] = data;
|
||||
}
|
||||
}
|
||||
|
||||
appState(obj, state) {
|
||||
const data = _.get(obj, 'appState', false);
|
||||
if (data) {
|
||||
state.apps[data.app].state = data.state;
|
||||
}
|
||||
}
|
||||
|
||||
appFailed(obj, state) {
|
||||
const data = _.get(obj, 'appFailed', false);
|
||||
if (data) {
|
||||
|
@ -10,8 +10,11 @@ export class Apps extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
this.state = {
|
||||
stateQuery: {}
|
||||
};
|
||||
|
||||
this.changeStateQuery = this.changeStateQuery.bind(this);
|
||||
this.loadApps = this.loadApps.bind(this);
|
||||
this.loadAppDetails = this.loadAppDetails.bind(this);
|
||||
}
|
||||
@ -27,6 +30,11 @@ export class Apps extends Component {
|
||||
//
|
||||
}
|
||||
|
||||
changeStateQuery(app, event) {
|
||||
this.state.stateQuery[app] = event.target.value;
|
||||
this.setState({ stateQuery: this.state.stateQuery });
|
||||
}
|
||||
|
||||
loadApps() {
|
||||
api.getApps();
|
||||
}
|
||||
@ -35,11 +43,14 @@ export class Apps extends Component {
|
||||
api.getAppDetails(app);
|
||||
}
|
||||
|
||||
loadAppState(app) {
|
||||
api.getAppState(app, this.state.stateQuery[app]);
|
||||
}
|
||||
|
||||
//TODO use classes for styling?
|
||||
render() {
|
||||
const { props, state } = this;
|
||||
|
||||
console.log('render', props.apps, Object.keys(props.apps));
|
||||
const apps = Object.keys(props.apps).sort().map(app => {
|
||||
const appData = props.apps[app];
|
||||
const haveDeets = (typeof appData === 'object');
|
||||
@ -71,8 +82,16 @@ export class Apps extends Component {
|
||||
>
|
||||
refresh
|
||||
</button>
|
||||
<button onClick={()=>{this.loadAppState(app)}}>query state</button>
|
||||
<textarea
|
||||
class="mono"
|
||||
onChange={(e) => this.changeStateQuery(app, e)}
|
||||
value={state.stateQuery[app]}
|
||||
placeholder="-.-"
|
||||
spellCheck="false"
|
||||
/>
|
||||
<div style={{maxHeight: '500px', overflow: 'scroll'}}>
|
||||
<pre>{data.state.join('\n')}</pre>
|
||||
<pre>{(data.state || data.simpleState).join('\n')}</pre>
|
||||
</div>
|
||||
<div>
|
||||
<Subscriptions {...data.subscriptions} />
|
||||
|
Loading…
Reference in New Issue
Block a user