forked from cerc-io/laconic-console
Local resolver.
This commit is contained in:
parent
b24fdfc57c
commit
ead184c3a9
6
.idea/jsLibraryMappings.xml
Normal file
6
.idea/jsLibraryMappings.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptLibraryMappings">
|
||||
<includedPredefinedLibrary name="Node.js Core" />
|
||||
</component>
|
||||
</project>
|
@ -6,11 +6,13 @@ Apollo GraphQL client and server using express.
|
||||
|
||||
### POC
|
||||
|
||||
- [ ] Test backend IPFS client request.
|
||||
- [ ] Trigger server-side wire commands (separate express path?)
|
||||
|
||||
### Next
|
||||
|
||||
- [ ] Routes.
|
||||
- [ ] Fix JsonTree (yarn link).
|
||||
- [ ] Client/server API abstraction (error handler, etc.)
|
||||
- [ ] Webpack config (remove dynamic config?)
|
||||
- [ ] https://github.com/standard/standardx (JSX)
|
||||
- [ ] Shared config.
|
||||
@ -18,6 +20,8 @@ Apollo GraphQL client and server using express.
|
||||
|
||||
### Done
|
||||
|
||||
- [c] Client resolvers: https://www.apollographql.com/docs/tutorial/local-state/
|
||||
- [x] Test backend IPFS client request.
|
||||
- [x] Hash Router.
|
||||
- [x] Layout (with Material UI).
|
||||
- [x] config from provider.
|
||||
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"app": {
|
||||
"org": "DxOS",
|
||||
"theme": "dark",
|
||||
"title": "Console",
|
||||
"website": "https://dxos.org",
|
||||
"publicUrl": "/console"
|
||||
},
|
||||
"graphql": {
|
||||
"path": "/api",
|
||||
"port": 4000,
|
||||
"pollInterval": 10000
|
||||
}
|
||||
}
|
43
packages/console-client/config.yml
Normal file
43
packages/console-client/config.yml
Normal file
@ -0,0 +1,43 @@
|
||||
#
|
||||
# NODE_ENV === production
|
||||
# NOTE: Set CONFIG_FILE to swap out this config file.
|
||||
#
|
||||
|
||||
app:
|
||||
title: 'Console'
|
||||
org': 'DxOS'
|
||||
theme: 'dark'
|
||||
website: 'https://dxos.org'
|
||||
publicUrl: '/console'
|
||||
|
||||
api:
|
||||
path: '/api'
|
||||
port: 4000
|
||||
pollInterval: 10000
|
||||
|
||||
system:
|
||||
debug: 'dxos:console:*'
|
||||
xbox:
|
||||
image: '/opt/xbox/IMAGE'
|
||||
|
||||
services:
|
||||
app:
|
||||
server: 'http://127.0.0.1:5999' # TODO(burdon): ???
|
||||
|
||||
wns:
|
||||
server: 'https://node1.dxos.network/wns/api'
|
||||
webui: 'https://node1.dxos.network/wns/webui'
|
||||
# server: 'http://127.0.0.1:9473/api'
|
||||
# webui: 'http://127.0.0.1:9473/webui'
|
||||
|
||||
signal:
|
||||
server: 'http://127.0.0.1:4000'
|
||||
api: 'http://127.0.0.1:4000' # TODO(burdon): ???
|
||||
|
||||
ipfs:
|
||||
server: '/ip4/127.0.0.1/tcp/5001'
|
||||
gateway: '/ip4//127.0.0.1:8888/ipfs/'
|
||||
webui: 'http://127.0.0.1:5001/webui'
|
||||
|
||||
wellknown:
|
||||
endpoint: 'http://127.0.0.1:9000/.well-known/dxos'
|
9
packages/console-client/gql/ipfs.graphql
Normal file
9
packages/console-client/gql/ipfs.graphql
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# Copyright 2020 DxOS
|
||||
#
|
||||
|
||||
{
|
||||
ipfs {
|
||||
json
|
||||
}
|
||||
}
|
9
packages/console-client/gql/wns.graphql
Normal file
9
packages/console-client/gql/wns.graphql
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# Copyright 2020 DxOS
|
||||
#
|
||||
|
||||
{
|
||||
wns {
|
||||
json @client
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
"description": "DxOS Console Client",
|
||||
"main": "dist/es/index.js",
|
||||
"files": [
|
||||
"config.json",
|
||||
"config.yml",
|
||||
"dist/production",
|
||||
"gql"
|
||||
],
|
||||
@ -33,6 +33,7 @@
|
||||
"@dxos/react-ux": "^1.0.0-beta.20",
|
||||
"@material-ui/core": "^4.10.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@wirelineio/registry-client": "^0.4.8",
|
||||
"apollo-cache-inmemory": "^1.6.6",
|
||||
"apollo-client": "^2.6.10",
|
||||
"apollo-link-http": "^1.5.17",
|
||||
@ -83,7 +84,8 @@
|
||||
"webpack-cli": "^3.3.10",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-merge": "^4.2.2",
|
||||
"webpack-version-file-plugin": "^0.4.0"
|
||||
"webpack-version-file-plugin": "^0.4.0",
|
||||
"yaml-loader": "^0.6.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -6,26 +6,39 @@ import { ApolloClient } from 'apollo-client';
|
||||
import { createHttpLink } from 'apollo-link-http';
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory';
|
||||
|
||||
import { createResolvers } from './resolvers';
|
||||
|
||||
const defaultServer = `${window.location.protocol}//${window.location.hostname}`;
|
||||
|
||||
export const graphqlApi = config => {
|
||||
const { graphql: { server = defaultServer, port = 80, path = '/graphql' } } = config;
|
||||
const { api: { server = defaultServer, port = 80, path = '/graphql' } } = config;
|
||||
|
||||
return `${server}:${port}${path}`;
|
||||
};
|
||||
|
||||
// https://www.apollographql.com/docs/react/api/apollo-client/
|
||||
/**
|
||||
* Craetes an Apollo client.
|
||||
* @param {Object} config
|
||||
* @returns {ApolloClient}
|
||||
*/
|
||||
export const clientFactory = config => {
|
||||
// TODO(burdon): Authentication: send signed message to server (from client wallet).
|
||||
// https://www.apollographql.com/docs/react/networking/authentication/
|
||||
|
||||
// https://www.apollographql.com/docs/link/
|
||||
const link = createHttpLink({
|
||||
uri: graphqlApi(config)
|
||||
uri: graphqlApi(config),
|
||||
|
||||
// TODO(burdon): Authentication: send signed message to server (from client wallet).
|
||||
// https://www.apollographql.com/docs/react/networking/authentication/
|
||||
headers: {
|
||||
authorization: 'HALO_TOKEN'
|
||||
}
|
||||
});
|
||||
|
||||
// https://www.apollographql.com/docs/react/api/apollo-client/
|
||||
return new ApolloClient({
|
||||
connectToDevTools: true,
|
||||
cache: new InMemoryCache(),
|
||||
resolvers: createResolvers(config),
|
||||
link
|
||||
});
|
||||
};
|
||||
|
@ -23,6 +23,7 @@ const removeTypename = data => transform(data, (result, value, key) => {
|
||||
const Json = ({ data }) => {
|
||||
const classes = useStyles();
|
||||
|
||||
// TODO(burdon): Bug expands when updated.
|
||||
return (
|
||||
<JsonTreeView className={classes.root} data={removeTypename(data)} />
|
||||
);
|
||||
|
@ -22,7 +22,8 @@ const useStyles = makeStyles((theme) => ({
|
||||
container: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flex: 1
|
||||
flex: 1,
|
||||
overflow: 'hidden'
|
||||
},
|
||||
sidebar: {
|
||||
display: 'flex',
|
||||
@ -33,7 +34,8 @@ const useStyles = makeStyles((theme) => ({
|
||||
},
|
||||
main: {
|
||||
display: 'flex',
|
||||
flex: 1
|
||||
flex: 1,
|
||||
overflow: 'hidden'
|
||||
},
|
||||
cooter: {
|
||||
display: 'flex',
|
||||
|
27
packages/console-client/src/containers/IPFS.js
Normal file
27
packages/console-client/src/containers/IPFS.js
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// Copyright 2020 DxOS
|
||||
//
|
||||
|
||||
import React, { useContext } from 'react';
|
||||
import { useQuery } from '@apollo/react-hooks';
|
||||
|
||||
import Json from '../components/Json';
|
||||
|
||||
import { ConsoleContext, useQueryStatusReducer } from '../hooks';
|
||||
|
||||
import QUERY from '../../gql/ipfs.graphql';
|
||||
|
||||
const IPFS = () => {
|
||||
const { config } = useContext(ConsoleContext);
|
||||
const data = useQueryStatusReducer(useQuery(QUERY, { pollInterval: config.api.pollInterval }));
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO(burdon): Return structured GraphQL.
|
||||
return (
|
||||
<Json data={{ ipfs: JSON.parse(data.ipfs.json) }} />
|
||||
);
|
||||
};
|
||||
|
||||
export default IPFS;
|
@ -2,13 +2,14 @@
|
||||
// Copyright 2020 DxOS
|
||||
//
|
||||
|
||||
import debug from 'debug';
|
||||
import React from 'react';
|
||||
import { HashRouter, Redirect, Route, Switch } from 'react-router-dom';
|
||||
import { ApolloProvider } from '@apollo/react-hooks';
|
||||
import { ThemeProvider } from '@material-ui/core/styles';
|
||||
import CssBaseline from '@material-ui/core/CssBaseline';
|
||||
|
||||
import config from '../../config.json';
|
||||
import config from '../../config.yml';
|
||||
|
||||
import { createTheme } from '../theme';
|
||||
import { clientFactory } from '../client';
|
||||
@ -19,7 +20,11 @@ import Layout from '../components/Layout';
|
||||
|
||||
import ConsoleContextProvider from './ConsoleContextProvider';
|
||||
|
||||
import IPFS from './IPFS';
|
||||
import Status from './Status';
|
||||
import WNS from './WNS';
|
||||
|
||||
debug.enable(config.system.debug);
|
||||
|
||||
const Main = () => {
|
||||
return (
|
||||
@ -31,8 +36,10 @@ const Main = () => {
|
||||
<Switch>
|
||||
<Route path="/:module">
|
||||
<Layout>
|
||||
<Route path="/status" component={Status} />
|
||||
<Route path="/config" component={Config} />
|
||||
<Route path="/ipfs" component={IPFS} />
|
||||
<Route path="/status" component={Status} />
|
||||
<Route path="/wns" component={WNS} />
|
||||
</Layout>
|
||||
</Route>
|
||||
<Redirect to="/status" />
|
||||
|
@ -2,9 +2,6 @@
|
||||
// Copyright 2020 DxOS
|
||||
//
|
||||
|
||||
import isObject from 'lodash.isobject';
|
||||
import omit from 'lodash.omit';
|
||||
import transform from 'lodash.transform';
|
||||
import React, { useContext } from 'react';
|
||||
import { useQuery } from '@apollo/react-hooks';
|
||||
|
||||
@ -12,22 +9,17 @@ import Json from '../components/Json';
|
||||
|
||||
import { ConsoleContext, useQueryStatusReducer } from '../hooks';
|
||||
|
||||
import QUERY_STATUS from '../../gql/status.graphql';
|
||||
|
||||
const removeTypename = data => transform(data, (result, value, key) => {
|
||||
result[key] = isObject(value) && '__typename' in value ? omit(value, '__typename') : value;
|
||||
});
|
||||
import QUERY from '../../gql/status.graphql';
|
||||
|
||||
const Status = () => {
|
||||
const { config } = useContext(ConsoleContext);
|
||||
|
||||
const data = useQueryStatusReducer(useQuery(QUERY_STATUS, { pollInterval: config.graphql.pollInterval }));
|
||||
const data = useQueryStatusReducer(useQuery(QUERY, { pollInterval: config.api.pollInterval }));
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Json data={removeTypename(data)} />
|
||||
<Json data={data} />
|
||||
);
|
||||
};
|
||||
|
||||
|
45
packages/console-client/src/containers/WNS.js
Normal file
45
packages/console-client/src/containers/WNS.js
Normal file
@ -0,0 +1,45 @@
|
||||
//
|
||||
// Copyright 2020 DxOS
|
||||
//
|
||||
|
||||
import React, { useContext } from 'react';
|
||||
import { useQuery } from '@apollo/react-hooks';
|
||||
import { makeStyles } from '@material-ui/core';
|
||||
|
||||
import Json from '../components/Json';
|
||||
|
||||
import { ConsoleContext, useQueryStatusReducer } from '../hooks';
|
||||
|
||||
import QUERY from '../../gql/wns.graphql';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flex: 1,
|
||||
overflowY: 'scroll'
|
||||
}
|
||||
}));
|
||||
|
||||
const WNS = () => {
|
||||
const classes = useStyles();
|
||||
const { config } = useContext(ConsoleContext);
|
||||
const data = useQueryStatusReducer(useQuery(QUERY, { pollInterval: config.api.pollInterval }));
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO(burdon): peers causes issues.
|
||||
// Warning: Failed prop type: Invalid prop `children` supplied to `ForwardRef(Typography)`, expected a ReactNode.
|
||||
const d = JSON.parse(data.wns.json);
|
||||
d.peers = [];
|
||||
|
||||
// TODO(burdon): Return structured GraphQL.
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<Json data={{ wns: d }} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WNS;
|
@ -2,12 +2,9 @@
|
||||
// Copyright 2020 DxOS
|
||||
//
|
||||
|
||||
import debug from 'debug';
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
|
||||
import Main from './containers/Main';
|
||||
|
||||
debug.enable('dxos:console:client:*');
|
||||
|
||||
render(<Main />, document.getElementById('root'));
|
||||
|
36
packages/console-client/src/resolvers.js
Normal file
36
packages/console-client/src/resolvers.js
Normal file
@ -0,0 +1,36 @@
|
||||
//
|
||||
// Copyright 2020 DxOS
|
||||
//
|
||||
|
||||
import debug from 'debug';
|
||||
|
||||
import { Registry } from '@wirelineio/registry-client';
|
||||
|
||||
const log = debug('dxos:console:client:resolvers');
|
||||
|
||||
//
|
||||
// Resolvers
|
||||
// https://www.apollographql.com/docs/tutorial/local-state/#local-resolvers
|
||||
//
|
||||
|
||||
export const createResolvers = config => {
|
||||
// TODO(burdon): Get route if served from xbox.
|
||||
const { services: { wns: { server } } } = config;
|
||||
|
||||
const registry = new Registry(server);
|
||||
|
||||
return {
|
||||
Query: {
|
||||
wns: async () => {
|
||||
log('Querying WNS...');
|
||||
|
||||
const status = await registry.getStatus();
|
||||
|
||||
return {
|
||||
__typename: 'JSONResult',
|
||||
json: JSON.stringify(status)
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"build": {
|
||||
"name": "@dxos/console-client",
|
||||
"buildDate": "2020-05-24T00:17:36.206Z",
|
||||
"buildDate": "2020-05-24T02:00:10.452Z",
|
||||
"version": "1.0.0-beta.0"
|
||||
}
|
||||
}
|
||||
|
@ -103,11 +103,18 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
// https://www.apollographql.com/docs/react/integrations/webpack/
|
||||
// https://github.com/eemeli/yaml-loader
|
||||
{
|
||||
test: /\.ya?ml$/,
|
||||
type: 'json',
|
||||
use: 'yaml-loader'
|
||||
},
|
||||
|
||||
// https://www.apollographql.com/docs/react/integrations/webpack
|
||||
{
|
||||
test: /\.(graphql|gql)$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'graphql-tag/loader',
|
||||
loader: 'graphql-tag/loader'
|
||||
},
|
||||
|
||||
// fonts
|
||||
|
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"lint": "semistandard 'src/**/*.js'",
|
||||
"test": "jest --rootDir ./src --passWithNoTests --no-cache",
|
||||
"start": "nodemon --exec babel-node ./src/main.js"
|
||||
"start": "BABEL_DISABLE_CACHE=1 nodemon --exec babel-node ./src/main.js"
|
||||
},
|
||||
"author": "DxOS.org",
|
||||
"license": "GPL-3.0",
|
||||
@ -26,6 +26,8 @@
|
||||
"express-graphql": "^0.9.0",
|
||||
"graphql": "^15.0.0",
|
||||
"graphql-tag": "^2.10.3",
|
||||
"ipfs-http-client": "^44.1.0",
|
||||
"js-yaml": "^3.14.0",
|
||||
"react-dom": "^16.13.1",
|
||||
"source-map-support": "^0.5.12"
|
||||
},
|
||||
@ -41,9 +43,9 @@
|
||||
"babel-plugin-add-module-exports": "^1.0.2",
|
||||
"babel-plugin-inline-import": "^3.0.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-loader": "^3.0.3",
|
||||
"eslint-config-semistandard": "^15.0.0",
|
||||
"eslint-config-standard": "^14.1.1",
|
||||
"eslint-loader": "^3.0.3",
|
||||
"eslint-plugin-babel": "^5.3.0",
|
||||
"eslint-plugin-import": "^2.18.2",
|
||||
"eslint-plugin-jest": "^23.13.1",
|
||||
|
@ -2,11 +2,21 @@
|
||||
# Copyright 2020 DxOS
|
||||
#
|
||||
|
||||
type JSONResult {
|
||||
json: String!
|
||||
}
|
||||
|
||||
type Status {
|
||||
timestamp: String
|
||||
version: String
|
||||
timestamp: String!
|
||||
version: String!
|
||||
}
|
||||
|
||||
type Query {
|
||||
status: Status
|
||||
ipfs: JSONResult
|
||||
wns: JSONResult
|
||||
}
|
||||
|
||||
schema {
|
||||
query: Query
|
||||
}
|
||||
|
@ -4,21 +4,24 @@
|
||||
|
||||
import debug from 'debug';
|
||||
import express from 'express';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import yaml from 'js-yaml';
|
||||
import { ApolloServer, gql } from 'apollo-server-express';
|
||||
import { print } from 'graphql/language';
|
||||
|
||||
import QUERY_STATUS from '@dxos/console-client/gql/status.graphql';
|
||||
import config from '@dxos/console-client/config.json';
|
||||
|
||||
import { resolvers } from './resolvers';
|
||||
|
||||
import SCHEMA from './gql/api.graphql';
|
||||
|
||||
const config = yaml.safeLoad(
|
||||
fs.readFileSync(path.join(__dirname, '../../../node_modules/@dxos/console-client/config.yml')));
|
||||
|
||||
const log = debug('dxos:console:server');
|
||||
|
||||
// TODO(burdon): Config.
|
||||
debug.enable('dxos:console:*');
|
||||
debug.enable(config.system.debug);
|
||||
|
||||
//
|
||||
// Express server.
|
||||
@ -69,7 +72,7 @@ const server = new ApolloServer({
|
||||
tabs: [
|
||||
{
|
||||
name: 'Status',
|
||||
endpoint: config.graphql.path,
|
||||
endpoint: config.api.path,
|
||||
query: print(gql(QUERY_STATUS))
|
||||
}
|
||||
]
|
||||
@ -83,13 +86,14 @@ const server = new ApolloServer({
|
||||
|
||||
server.applyMiddleware({
|
||||
app,
|
||||
path: config.graphql.path
|
||||
path: config.api.path
|
||||
});
|
||||
|
||||
//
|
||||
// Start server
|
||||
//
|
||||
|
||||
app.listen({ port: config.graphql.port }, () => {
|
||||
log(`Running: http://localhost:${config.graphql.port}`);
|
||||
const { api: { port } } = config;
|
||||
app.listen({ port }, () => {
|
||||
log(`Running: http://localhost:${port}`);
|
||||
});
|
||||
|
@ -2,21 +2,48 @@
|
||||
// Copyright 2020 DxOS
|
||||
//
|
||||
|
||||
// import debug from 'debug';
|
||||
import debug from 'debug';
|
||||
import IpfsHttpClient from 'ipfs-http-client';
|
||||
|
||||
import { version } from '../package.json';
|
||||
|
||||
// const log = debug('dxos:console:resolver');
|
||||
const log = debug('dxos:console:server:resolvers');
|
||||
|
||||
//
|
||||
// Resolver
|
||||
// Resolvers
|
||||
//
|
||||
|
||||
export const resolvers = {
|
||||
Query: {
|
||||
//
|
||||
// Status
|
||||
//
|
||||
status: () => ({
|
||||
timestamp: new Date().toUTCString(),
|
||||
version
|
||||
})
|
||||
}),
|
||||
|
||||
//
|
||||
// IPFS
|
||||
// TODO(burdon): Call from client?
|
||||
// https://github.com/ipfs/js-ipfs
|
||||
// https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-http-client#api
|
||||
//
|
||||
ipfs: async () => {
|
||||
log('Calling IPFS...');
|
||||
|
||||
// TODO(burdon): Config.
|
||||
const ipfs = new IpfsHttpClient('/ip4/127.0.0.1/tcp/5001');
|
||||
|
||||
const version = await ipfs.version();
|
||||
const status = await ipfs.id();
|
||||
|
||||
return {
|
||||
json: JSON.stringify({
|
||||
version,
|
||||
status
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user