forked from cerc-io/laconic-console
commit
c831181c1d
@ -14,7 +14,7 @@ First start the server:
|
|||||||
Then start the Webpack devserver.
|
Then start the Webpack devserver.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd packages/consoe-app
|
cd packages/console-app
|
||||||
yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
30
packages/console-app/src/components/BooleanIcon.js
Normal file
30
packages/console-app/src/components/BooleanIcon.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DxOS
|
||||||
|
//
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import YesIcon from '@material-ui/icons/CheckCircleOutline';
|
||||||
|
import NoIcon from '@material-ui/icons/RadioButtonUnchecked';
|
||||||
|
|
||||||
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
|
const useStyles = makeStyles(theme => ({
|
||||||
|
error: {
|
||||||
|
color: theme.palette.error.main
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
color: theme.palette.primary[500]
|
||||||
|
},
|
||||||
|
off: {
|
||||||
|
color: 'transparent'
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const BooleanIcon = ({ yes = false, error = false }) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
return (yes
|
||||||
|
? <YesIcon className={classes.on} />
|
||||||
|
: <NoIcon className={error ? classes.error : classes.off} />
|
||||||
|
);
|
||||||
|
};
|
@ -26,18 +26,22 @@ const useStyles = makeStyles(theme => ({
|
|||||||
const VersionCheck = () => {
|
const VersionCheck = () => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [{ current, latest }, setUpgrade] = useState({});
|
const [{ current, latest }, setUpgrade] = useState({});
|
||||||
const status = useQueryStatusReducer(useQuery(SYSTEM_STATUS));
|
const statusRespone = useQueryStatusReducer(useQuery(SYSTEM_STATUS));
|
||||||
const data = useQueryStatusReducer(useQuery(WNS_RECORDS, {
|
const wnsResponse = useQueryStatusReducer(useQuery(WNS_RECORDS, {
|
||||||
pollInterval: CHECK_INTERVAL,
|
pollInterval: CHECK_INTERVAL,
|
||||||
variables: { type: 'wrn:resource' }
|
variables: { attributes: { type: 'wrn:resource' } }
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Check version.
|
// Check version.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (status && data) {
|
if (statusRespone && wnsResponse) {
|
||||||
const { dxos: { image: current } } = status.system_status;
|
const statusData = JSON.parse(statusRespone.system_status.json);
|
||||||
|
const wnsData = JSON.parse(wnsResponse.wns_records.json);
|
||||||
|
|
||||||
|
const { dxos: { image: current = '0.0.0' } = {} } = statusData;
|
||||||
|
|
||||||
let latest = current;
|
let latest = current;
|
||||||
data.wns_records.json.forEach(({ attributes: { name, version } }) => {
|
wnsData.forEach(({ attributes: { name, version } }) => {
|
||||||
// TODO(burdon): Filter by type (WRN?)
|
// TODO(burdon): Filter by type (WRN?)
|
||||||
if (name.startsWith('dxos/xbox:')) {
|
if (name.startsWith('dxos/xbox:')) {
|
||||||
if (compareVersions(version, latest) > 0) {
|
if (compareVersions(version, latest) > 0) {
|
||||||
@ -48,7 +52,7 @@ const VersionCheck = () => {
|
|||||||
|
|
||||||
setUpgrade({ current, latest: latest !== current ? latest : undefined });
|
setUpgrade({ current, latest: latest !== current ? latest : undefined });
|
||||||
}
|
}
|
||||||
}, [status, data]);
|
}, [status, wnsResponse]);
|
||||||
|
|
||||||
// TODO(burdon): Link to Github page with upgrade info.
|
// TODO(burdon): Link to Github page with upgrade info.
|
||||||
return (
|
return (
|
||||||
|
@ -16,18 +16,20 @@ import Toolbar from '../../components/Toolbar';
|
|||||||
|
|
||||||
const Status = () => {
|
const Status = () => {
|
||||||
const { config } = useContext(ConsoleContext);
|
const { config } = useContext(ConsoleContext);
|
||||||
const data = useQueryStatusReducer(useQuery(SYSTEM_STATUS, { pollInterval: config.api.intervalQuery }));
|
const systemResponse = useQueryStatusReducer(useQuery(SYSTEM_STATUS, { pollInterval: config.api.intervalQuery }));
|
||||||
if (!data) {
|
if (!systemResponse) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const data = JSON.parse(systemResponse.system_status.json);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Panel
|
<Panel
|
||||||
toolbar={
|
toolbar={
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Json data={data.system_status} />
|
<Json data={data} />
|
||||||
</Panel>
|
</Panel>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -3,36 +3,43 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
import { useQuery } from '@apollo/react-hooks';
|
import { useQuery } from '@apollo/react-hooks';
|
||||||
|
|
||||||
import WNS_RECORDS from '../../../gql/wns_records.graphql';
|
|
||||||
|
|
||||||
import { ConsoleContext, useQueryStatusReducer, useSorter } from '../../../hooks';
|
|
||||||
|
|
||||||
import Link from '@material-ui/core/Link';
|
import Link from '@material-ui/core/Link';
|
||||||
import TableHead from '@material-ui/core/TableHead';
|
import TableHead from '@material-ui/core/TableHead';
|
||||||
import TableRow from '@material-ui/core/TableRow';
|
import TableRow from '@material-ui/core/TableRow';
|
||||||
import TableBody from '@material-ui/core/TableBody';
|
import TableBody from '@material-ui/core/TableBody';
|
||||||
|
|
||||||
import { getServiceUrl } from '../../../util/config';
|
import IPFS_STATUS from '../../../gql/ipfs_status.graphql';
|
||||||
|
import WNS_RECORDS from '../../../gql/wns_records.graphql';
|
||||||
|
|
||||||
|
import { ConsoleContext, useQueryStatusReducer, useSorter } from '../../../hooks';
|
||||||
|
|
||||||
|
import { BooleanIcon } from '../../../components/BooleanIcon';
|
||||||
import Table from '../../../components/Table';
|
import Table from '../../../components/Table';
|
||||||
import TableCell from '../../../components/TableCell';
|
import TableCell from '../../../components/TableCell';
|
||||||
import moment from 'moment';
|
import { getServiceUrl } from '../../../util/config';
|
||||||
|
|
||||||
const AppRecords = () => {
|
const AppRecords = () => {
|
||||||
const { config } = useContext(ConsoleContext);
|
const { config } = useContext(ConsoleContext);
|
||||||
const [sorter, sortBy] = useSorter('createTime', false);
|
const [sorter, sortBy] = useSorter('createTime', false);
|
||||||
const data = useQueryStatusReducer(useQuery(WNS_RECORDS, {
|
const appResponse = useQueryStatusReducer(useQuery(WNS_RECORDS, {
|
||||||
pollInterval: config.api.intervalQuery,
|
pollInterval: config.api.intervalQuery,
|
||||||
variables: { type: 'wrn:app' }
|
variables: { attributes: { type: 'wrn:app' } }
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (!data) {
|
// TODO(telackey): Does this also need an interval?
|
||||||
|
const ipfsResponse = useQueryStatusReducer(useQuery(IPFS_STATUS));
|
||||||
|
|
||||||
|
if (!appResponse || !ipfsResponse) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const records = data.wns_records.json;
|
const appData = JSON.parse(appResponse.wns_records.json);
|
||||||
|
const ipfsData = JSON.parse(ipfsResponse.ipfs_status.json);
|
||||||
|
|
||||||
|
const localRefs = new Set(ipfsData.refs.local);
|
||||||
|
|
||||||
// TODO(burdon): Test if app is deployed.
|
// TODO(burdon): Test if app is deployed.
|
||||||
const getAppUrl = ({ name, version }) => {
|
const getAppUrl = ({ name, version }) => {
|
||||||
@ -47,8 +54,12 @@ const AppRecords = () => {
|
|||||||
pathComponents.push(config.services.app.prefix.substring(1));
|
pathComponents.push(config.services.app.prefix.substring(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version) {
|
||||||
pathComponents.push(`${name}@${version}`);
|
pathComponents.push(`${name}@${version}`);
|
||||||
return pathComponents.join('/');
|
} else {
|
||||||
|
pathComponents.push(name);
|
||||||
|
}
|
||||||
|
return `${pathComponents.join('/')}/`;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -56,26 +67,29 @@ const AppRecords = () => {
|
|||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell onClick={sortBy('name')}>Identifier</TableCell>
|
<TableCell onClick={sortBy('name')}>Identifier</TableCell>
|
||||||
|
<TableCell onClick={sortBy('attributes.displayName')}>Name</TableCell>
|
||||||
<TableCell onClick={sortBy('version')} size='small'>Version</TableCell>
|
<TableCell onClick={sortBy('version')} size='small'>Version</TableCell>
|
||||||
<TableCell onClick={sortBy('createTime')} size='small'>Created</TableCell>
|
<TableCell onClick={sortBy('createTime')} size='small'>Created</TableCell>
|
||||||
<TableCell onClick={sortBy('attributes.displayName')}>Name</TableCell>
|
<TableCell size='small'>Downloaded</TableCell>
|
||||||
<TableCell>Link</TableCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{records.sort(sorter).map(({ id, name, version, createTime, attributes: { displayName, publicUrl } }) => {
|
{appData.sort(sorter).map(({ id, name, version, createTime, attributes: { displayName, publicUrl, package: hash } }) => {
|
||||||
const link = getAppUrl({ id, name, version, publicUrl });
|
const verLink = getAppUrl({ id, name, version, publicUrl });
|
||||||
|
const appLink = getAppUrl({ id, name, publicUrl });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow key={id} size='small'>
|
<TableRow key={id} size='small'>
|
||||||
<TableCell monospace>{name}</TableCell>
|
<TableCell monospace>
|
||||||
<TableCell monospace>{version}</TableCell>
|
<Link href={appLink} target={name}>{name}</Link>
|
||||||
<TableCell>{moment.utc(createTime).fromNow()}</TableCell>
|
</TableCell>
|
||||||
<TableCell>{displayName}</TableCell>
|
<TableCell>{displayName}</TableCell>
|
||||||
<TableCell monospace>
|
<TableCell monospace>
|
||||||
{link && (
|
<Link href={verLink} target={version}>{version}</Link>
|
||||||
<Link href={link} target={name}>{link}</Link>
|
</TableCell>
|
||||||
)}
|
<TableCell>{moment.utc(createTime).fromNow()}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<BooleanIcon yes={localRefs && localRefs.has(hash)} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
|
@ -3,29 +3,157 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import get from 'lodash.get';
|
||||||
|
|
||||||
import { useQuery } from '@apollo/react-hooks';
|
import { useQuery } from '@apollo/react-hooks';
|
||||||
|
import { makeStyles } from '@material-ui/core';
|
||||||
|
import TableBody from '@material-ui/core/TableBody';
|
||||||
|
import TableHead from '@material-ui/core/TableHead';
|
||||||
|
import TableRow from '@material-ui/core/TableRow';
|
||||||
|
|
||||||
import IPFS_STATUS from '../../../gql/ipfs_status.graphql';
|
import IPFS_STATUS from '../../../gql/ipfs_status.graphql';
|
||||||
|
import WNS_RECORDS from '../../../gql/wns_records.graphql';
|
||||||
|
|
||||||
import { useQueryStatusReducer } from '../../../hooks';
|
import { useQueryStatusReducer } from '../../../hooks';
|
||||||
|
|
||||||
import Json from '../../../components/Json';
|
import Json from '../../../components/Json';
|
||||||
import Panel from '../../../components/Panel';
|
import Panel from '../../../components/Panel';
|
||||||
|
import Table from '../../../components/Table';
|
||||||
|
import TableCell from '../../../components/TableCell';
|
||||||
import Toolbar from '../../../components/Toolbar';
|
import Toolbar from '../../../components/Toolbar';
|
||||||
|
import { BooleanIcon } from '../../../components/BooleanIcon';
|
||||||
|
|
||||||
|
const RECORD_TYPE = 'wrn:service';
|
||||||
|
const SERVICE_TYPE = 'ipfs';
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme) => ({
|
||||||
|
tableContainer: {
|
||||||
|
flex: 1,
|
||||||
|
overflowY: 'scroll'
|
||||||
|
},
|
||||||
|
|
||||||
|
table: {
|
||||||
|
tableLayout: 'fixed',
|
||||||
|
|
||||||
|
'& th': {
|
||||||
|
fontVariant: 'all-small-caps',
|
||||||
|
fontSize: 18,
|
||||||
|
cursor: 'ns-resize'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
connected: {
|
||||||
|
fontWeight: 'bold'
|
||||||
|
},
|
||||||
|
|
||||||
|
disconnected: {
|
||||||
|
fontStyle: 'italic'
|
||||||
|
},
|
||||||
|
|
||||||
|
colShort: {
|
||||||
|
width: '30%'
|
||||||
|
},
|
||||||
|
|
||||||
|
colWide: {},
|
||||||
|
|
||||||
|
colBoolean: {
|
||||||
|
width: '10%'
|
||||||
|
},
|
||||||
|
|
||||||
|
caption: {
|
||||||
|
backgroundColor: theme.palette.primary[500],
|
||||||
|
color: theme.palette.primary.contrastText,
|
||||||
|
paddingLeft: '1em',
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
const IPFS = () => {
|
const IPFS = () => {
|
||||||
const data = useQueryStatusReducer(useQuery(IPFS_STATUS));
|
const classes = useStyles();
|
||||||
if (!data) {
|
const ipfsResponse = useQueryStatusReducer(useQuery(IPFS_STATUS));
|
||||||
|
const wnsResponse = useQueryStatusReducer(useQuery(WNS_RECORDS, {
|
||||||
|
variables: { attributes: { type: RECORD_TYPE, service: SERVICE_TYPE } }
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!wnsResponse || !ipfsResponse) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ipfsData = JSON.parse(ipfsResponse.ipfs_status.json);
|
||||||
|
const registeredServers = JSON.parse(wnsResponse.wns_records.json);
|
||||||
|
|
||||||
|
const displayServers = registeredServers.map((service) => {
|
||||||
|
console.error(service);
|
||||||
|
const addresses = get(service, 'attributes.ipfs.addresses');
|
||||||
|
let connected = false;
|
||||||
|
for (const address of addresses) {
|
||||||
|
const parts = address.split('/');
|
||||||
|
const nodeId = parts[parts.length - 1];
|
||||||
|
connected = !!ipfsData.swarm.peers.find(({ peer }) => peer === nodeId);
|
||||||
|
if (connected) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: get(service, 'name'),
|
||||||
|
version: get(service, 'version'),
|
||||||
|
description: get(service, 'attributes.description'),
|
||||||
|
ipfs: get(service, 'attributes.ipfs'),
|
||||||
|
connected
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
displayServers.sort((a, b) => {
|
||||||
|
return a.connected && !b.connected ? -1 : b.connected && !a.connected ? 1 : b.name < a.name ? 1 : -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (displayServers.length === 0) {
|
||||||
|
displayServers.push({ name: 'None' });
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Panel
|
<Panel
|
||||||
toolbar={
|
toolbar={
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Json data={JSON.parse(data.ipfs_status.json)} />
|
<h4 className={classes.caption}>WNS-registered IPFS Servers</h4>
|
||||||
|
<Table stickyHeader size='small' className={classes.table}>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell size=''>Identifier</TableCell>
|
||||||
|
<TableCell size='small'>Description</TableCell>
|
||||||
|
<TableCell size='small'>Connected</TableCell>
|
||||||
|
<TableCell>Address</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{displayServers.map(({ name, description, ipfs, connected }) => (
|
||||||
|
<TableRow key={name}>
|
||||||
|
<TableCell>{name}</TableCell>
|
||||||
|
<TableCell>{description}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<BooleanIcon yes={connected} />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{ipfs.addresses}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
<h4 className={classes.caption}>Local IPFS Server</h4>
|
||||||
|
<Json data={{
|
||||||
|
id: ipfsData.id.id,
|
||||||
|
version: ipfsData.id.agentVersion,
|
||||||
|
addresses: ipfsData.id.addresses,
|
||||||
|
peers: ipfsData.swarm.peers.length,
|
||||||
|
numObjects: ipfsData.repo.stats.numObjects,
|
||||||
|
repoSize: ipfsData.repo.stats.repoSize
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Panel>
|
</Panel>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,18 +4,7 @@
|
|||||||
|
|
||||||
query {
|
query {
|
||||||
system_status {
|
system_status {
|
||||||
timestamp
|
timestamp,
|
||||||
dxos {
|
json
|
||||||
image
|
|
||||||
}
|
|
||||||
system {
|
|
||||||
network {
|
|
||||||
address
|
|
||||||
}
|
|
||||||
nodejs {
|
|
||||||
version
|
|
||||||
environment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright 2020 DxOS.org
|
|
||||||
#
|
|
||||||
|
|
||||||
mutation ($command: String!) {
|
|
||||||
wns_action(command: $command) {
|
|
||||||
timestamp
|
|
||||||
code
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,8 +2,10 @@
|
|||||||
# Copyright 2020 DxOS.org
|
# Copyright 2020 DxOS.org
|
||||||
#
|
#
|
||||||
|
|
||||||
query ($type: String) {
|
# TODO(telackey): Object would probably not be legal in general, but does work for a '@client' resolved query.
|
||||||
wns_records (type: $type) @client {
|
# When we do strong typing across the board we should replace it with something like KeyValueInput.
|
||||||
|
query ($attributes: Object) {
|
||||||
|
wns_records (attributes: $attributes) @client {
|
||||||
timestamp
|
timestamp
|
||||||
json
|
json
|
||||||
}
|
}
|
||||||
|
@ -43,16 +43,17 @@ export const createResolvers = config => {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
wns_records: async (_, { type }) => {
|
wns_records: async (_, { attributes }) => {
|
||||||
|
console.error(attributes);
|
||||||
log('WNS records...');
|
log('WNS records...');
|
||||||
const data = await registry.queryRecords({ type });
|
const data = await registry.queryRecords(attributes);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
__typename: 'JSONResult',
|
__typename: 'JSONResult',
|
||||||
timestamp: timestamp(),
|
timestamp: timestamp(),
|
||||||
|
|
||||||
// NOTE: Hack since this should be a string according to the schema.
|
// NOTE: Hack since this should be a string according to the schema.
|
||||||
json: data
|
json: JSON.stringify(data)
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"build": {
|
|
||||||
"name": "@dxos/console-app",
|
|
||||||
"buildDate": "2020-06-01T01:13:48.575Z",
|
|
||||||
"version": "1.0.0-beta.0"
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,26 +2,7 @@
|
|||||||
# Copyright 2020 DxOS.org
|
# Copyright 2020 DxOS.org
|
||||||
#
|
#
|
||||||
|
|
||||||
type DXOSInfo {
|
|
||||||
image: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type NetworkInfo {
|
|
||||||
address: [String]
|
|
||||||
}
|
|
||||||
|
|
||||||
type NodeInfo {
|
|
||||||
version: String
|
|
||||||
environment: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type SystemInfo {
|
|
||||||
network: NetworkInfo
|
|
||||||
nodejs: NodeInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
type SystemStatus {
|
type SystemStatus {
|
||||||
timestamp: String!
|
timestamp: String!
|
||||||
dxos: DXOSInfo
|
json: String!
|
||||||
system: SystemInfo
|
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,36 @@ export const ipfsResolvers = {
|
|||||||
// NOTE: Hangs if server not running.
|
// NOTE: Hangs if server not running.
|
||||||
const ipfs = new IpfsHttpClient(config.services.ipfs.server);
|
const ipfs = new IpfsHttpClient(config.services.ipfs.server);
|
||||||
|
|
||||||
|
const id = await ipfs.id();
|
||||||
const version = await ipfs.version();
|
const version = await ipfs.version();
|
||||||
const status = await ipfs.id();
|
const peers = await ipfs.swarm.peers();
|
||||||
|
const stats = await ipfs.stats.repo();
|
||||||
|
// Do not expose the repo path.
|
||||||
|
delete stats.repoPath;
|
||||||
|
|
||||||
|
const refs = [];
|
||||||
|
for await (const ref of ipfs.refs.local()) {
|
||||||
|
if (ref.err) {
|
||||||
|
log(ref.err);
|
||||||
|
} else {
|
||||||
|
refs.push(ref.ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
timestamp: new Date().toUTCString(),
|
timestamp: new Date().toUTCString(),
|
||||||
json: JSON.stringify({
|
json: JSON.stringify({
|
||||||
|
id,
|
||||||
version,
|
version,
|
||||||
status
|
repo: {
|
||||||
|
stats
|
||||||
|
},
|
||||||
|
refs: {
|
||||||
|
local: refs
|
||||||
|
},
|
||||||
|
swarm: {
|
||||||
|
peers
|
||||||
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,9 @@ const getSystemInfo = async () => {
|
|||||||
const ifaces = os.networkInterfaces();
|
const ifaces = os.networkInterfaces();
|
||||||
const addresses = Object.entries(ifaces).reduce((result, [, values]) => {
|
const addresses = Object.entries(ifaces).reduce((result, [, values]) => {
|
||||||
values.forEach(({ family, address }) => {
|
values.forEach(({ family, address }) => {
|
||||||
if (family === 'IPv4' && address !== '127.0.0.1') {
|
address = address.toLowerCase();
|
||||||
|
// TODO(telackey): Include link-local IPv6?
|
||||||
|
if (!address.startsWith('127.') && !address.startsWith('fe80::') && !address.startsWith('::1')) {
|
||||||
result.push(address);
|
result.push(address);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -42,7 +44,7 @@ const getSystemInfo = async () => {
|
|||||||
const device = await si.system();
|
const device = await si.system();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cpu: pick(cpu, 'brand', 'cores', 'manufacturer', 'vendor'),
|
cpu: pick(cpu, 'brand', 'cores', 'manufacturer', 'vendor', 'speed'),
|
||||||
|
|
||||||
memory: {
|
memory: {
|
||||||
total: size(memory.total, 'M'),
|
total: size(memory.total, 'M'),
|
||||||
@ -54,21 +56,23 @@ const getSystemInfo = async () => {
|
|||||||
device: pick(device, 'model', 'serial', 'version'),
|
device: pick(device, 'model', 'serial', 'version'),
|
||||||
|
|
||||||
network: {
|
network: {
|
||||||
address: addresses
|
addresses
|
||||||
},
|
},
|
||||||
|
|
||||||
// https://nodejs.org/api/os.html
|
// https://nodejs.org/api/os.html
|
||||||
os: {
|
os: {
|
||||||
arch: os.arch(),
|
arch: os.arch(),
|
||||||
type: os.type(),
|
|
||||||
platform: os.platform(),
|
platform: os.platform(),
|
||||||
version: os.version ? os.version() : undefined, // Node > 13
|
version: os.version ? os.version() : undefined // Node > 13
|
||||||
uptime: moment().subtract(os.uptime(), 'seconds').fromNow()
|
},
|
||||||
|
|
||||||
|
time: {
|
||||||
|
now: moment(),
|
||||||
|
up: moment().subtract(os.uptime(), 'seconds')
|
||||||
},
|
},
|
||||||
|
|
||||||
nodejs: {
|
nodejs: {
|
||||||
version: process.version,
|
version: process.version
|
||||||
environment: process.env.NODE_ENV
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -80,11 +84,7 @@ export const systemResolvers = {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
timestamp: new Date().toUTCString(),
|
timestamp: new Date().toUTCString(),
|
||||||
dxos: {
|
json: JSON.stringify(system)
|
||||||
// TODO(burdon): ???
|
|
||||||
image: '0.0.1'
|
|
||||||
},
|
|
||||||
system
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user