forked from cerc-io/laconic-console
Test mutation.
This commit is contained in:
parent
ead184c3a9
commit
5476d9fce8
14
README.md
14
README.md
@ -6,17 +6,19 @@ Apollo GraphQL client and server using express.
|
|||||||
|
|
||||||
### POC
|
### POC
|
||||||
|
|
||||||
- [ ] Trigger server-side wire commands (separate express path?)
|
- [ ] Trigger server-side wire commands (mutation or separate express path?)
|
||||||
|
|
||||||
### Next
|
### Next
|
||||||
|
|
||||||
- [ ] Routes.
|
- [ ] Config routes for services (test).
|
||||||
- [ ] Fix JsonTree (yarn link).
|
|
||||||
- [ ] Client/server API abstraction (error handler, etc.)
|
|
||||||
- [ ] Webpack config (remove dynamic config?)
|
- [ ] Webpack config (remove dynamic config?)
|
||||||
|
|
||||||
|
- [ ] Client/server API abstraction (error handler, etc.)
|
||||||
|
- [ ] Port dashboard API calls (resolve config first).
|
||||||
|
- [ ] Port dashboard react modules with dummy resolvers.
|
||||||
|
|
||||||
|
- [ ] Fix JsonTree (yarn link).
|
||||||
- [ ] https://github.com/standard/standardx (JSX)
|
- [ ] https://github.com/standard/standardx (JSX)
|
||||||
- [ ] Shared config.
|
|
||||||
- [ ] Port dashboard modules with dummy resolvers.
|
|
||||||
|
|
||||||
### Done
|
### Done
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ This creates the following folders:
|
|||||||
NOTE: GQL and Production files and exported and may be used by the server.
|
NOTE: GQL and Production files and exported and may be used by the server.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import QUERY_STATUS from '@dxos/console-client/gql/status.graphql';
|
import QUERY_STATUS from '@dxos/console-client/gql/system_status.graphql';
|
||||||
import config from '@dxos/console-client/config.json';
|
import config from '@dxos/console-client/config.json';
|
||||||
|
|
||||||
...
|
...
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
app:
|
app:
|
||||||
title: 'Console'
|
title: 'Console'
|
||||||
org': 'DxOS'
|
org': 'DxOS'
|
||||||
theme: 'dark'
|
theme: 'light'
|
||||||
website: 'https://dxos.org'
|
website: 'https://dxos.org'
|
||||||
publicUrl: '/console'
|
publicUrl: '/console'
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
{
|
{
|
||||||
ipfs {
|
ipfs_status {
|
||||||
json
|
json
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
{
|
{
|
||||||
status {
|
system_status {
|
||||||
timestamp
|
timestamp
|
||||||
version
|
version
|
||||||
}
|
}
|
10
packages/console-client/gql/wns_action.graphql
Normal file
10
packages/console-client/gql/wns_action.graphql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2020 DxOS
|
||||||
|
#
|
||||||
|
|
||||||
|
mutation Action($command: String!) {
|
||||||
|
wns_action(command: $command) {
|
||||||
|
timestamp
|
||||||
|
code
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
{
|
{
|
||||||
wns {
|
wns_status @client {
|
||||||
json @client
|
json
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,6 +27,7 @@
|
|||||||
"testEnvironment": "node"
|
"testEnvironment": "node"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@apollo/react-components": "^3.1.5",
|
||||||
"@apollo/react-hooks": "^3.1.5",
|
"@apollo/react-hooks": "^3.1.5",
|
||||||
"@babel/runtime": "^7.8.7",
|
"@babel/runtime": "^7.8.7",
|
||||||
"@dxos/gem-core": "^1.0.0-beta.11",
|
"@dxos/gem-core": "^1.0.0-beta.11",
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root-level error boundary.
|
* Root-level error boundary.
|
||||||
@ -34,7 +35,10 @@ class ErrorBoundary extends Component {
|
|||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
|
<div>
|
||||||
|
<Typography>Error</Typography>
|
||||||
<pre>{String(error)}</pre>
|
<pre>{String(error)}</pre>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,9 +16,16 @@ const useStyles = makeStyles(() => ({
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove Apollo __typename directive.
|
||||||
|
* @param {Object} data
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
const removeTypename = data => transform(data, (result, value, key) => {
|
const removeTypename = data => transform(data, (result, value, key) => {
|
||||||
result[key] = isObject(value) && '__typename' in value ? omit(value, '__typename') : value;
|
if (key !== '__typename') {
|
||||||
});
|
result[key] = isObject(value) ? ('__typename' in value ? omit(value, '__typename') : value) : value;
|
||||||
|
}
|
||||||
|
}, {});
|
||||||
|
|
||||||
const Json = ({ data }) => {
|
const Json = ({ data }) => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
@ -17,7 +17,8 @@ const useStyles = makeStyles((theme) => ({
|
|||||||
root: {
|
root: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
flex: 1
|
flex: 1,
|
||||||
|
overflow: 'hidden'
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -25,19 +26,19 @@ const useStyles = makeStyles((theme) => ({
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
overflow: 'hidden'
|
overflow: 'hidden'
|
||||||
},
|
},
|
||||||
sidebar: {
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
flexShrink: 0,
|
|
||||||
width: 180,
|
|
||||||
borderRight: `1px solid ${theme.palette.primary.dark}`
|
|
||||||
},
|
|
||||||
main: {
|
main: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
overflow: 'hidden'
|
overflow: 'hidden'
|
||||||
},
|
},
|
||||||
cooter: {
|
sidebar: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
flexShrink: 0,
|
||||||
|
width: 200,
|
||||||
|
borderRight: `1px solid ${theme.palette.primary.dark}`
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexShrink: 0
|
flexShrink: 0
|
||||||
}
|
}
|
||||||
|
@ -2,25 +2,23 @@
|
|||||||
// Copyright 2020 DxOS
|
// Copyright 2020 DxOS
|
||||||
//
|
//
|
||||||
|
|
||||||
import React, { useContext } from 'react';
|
import React from 'react';
|
||||||
import { useQuery } from '@apollo/react-hooks';
|
import { useQuery } from '@apollo/react-hooks';
|
||||||
|
|
||||||
import Json from '../components/Json';
|
import Json from '../components/Json';
|
||||||
|
|
||||||
import { ConsoleContext, useQueryStatusReducer } from '../hooks';
|
import { useQueryStatusReducer } from '../hooks';
|
||||||
|
|
||||||
import QUERY from '../../gql/ipfs.graphql';
|
import IPFS_STATUS from '../../gql/ipfs_status.graphql';
|
||||||
|
|
||||||
const IPFS = () => {
|
const IPFS = () => {
|
||||||
const { config } = useContext(ConsoleContext);
|
const data = useQueryStatusReducer(useQuery(IPFS_STATUS));
|
||||||
const data = useQueryStatusReducer(useQuery(QUERY, { pollInterval: config.api.pollInterval }));
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(burdon): Return structured GraphQL.
|
|
||||||
return (
|
return (
|
||||||
<Json data={{ ipfs: JSON.parse(data.ipfs.json) }} />
|
<Json data={JSON.parse(data.ipfs_status.json)} />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,17 +9,17 @@ import Json from '../components/Json';
|
|||||||
|
|
||||||
import { ConsoleContext, useQueryStatusReducer } from '../hooks';
|
import { ConsoleContext, useQueryStatusReducer } from '../hooks';
|
||||||
|
|
||||||
import QUERY from '../../gql/status.graphql';
|
import SYSTEM_STATUS from '../../gql/system_status.graphql';
|
||||||
|
|
||||||
const Status = () => {
|
const Status = () => {
|
||||||
const { config } = useContext(ConsoleContext);
|
const { config } = useContext(ConsoleContext);
|
||||||
const data = useQueryStatusReducer(useQuery(QUERY, { pollInterval: config.api.pollInterval }));
|
const data = useQueryStatusReducer(useQuery(SYSTEM_STATUS, { pollInterval: config.api.pollInterval }));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Json data={data} />
|
<Json data={data.system_status} />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,13 +4,16 @@
|
|||||||
|
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { useQuery } from '@apollo/react-hooks';
|
import { useQuery } from '@apollo/react-hooks';
|
||||||
|
import { Mutation } from '@apollo/react-components';
|
||||||
import { makeStyles } from '@material-ui/core';
|
import { makeStyles } from '@material-ui/core';
|
||||||
|
import Button from '@material-ui/core/Button';
|
||||||
|
|
||||||
import Json from '../components/Json';
|
import Json from '../components/Json';
|
||||||
|
|
||||||
import { ConsoleContext, useQueryStatusReducer } from '../hooks';
|
import { ConsoleContext, useQueryStatusReducer } from '../hooks';
|
||||||
|
|
||||||
import QUERY from '../../gql/wns.graphql';
|
import WNS_STATUS from '../../gql/wns_status.graphql';
|
||||||
|
import WNS_ACTION from '../../gql/wns_action.graphql';
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
root: {
|
root: {
|
||||||
@ -24,20 +27,30 @@ const useStyles = makeStyles((theme) => ({
|
|||||||
const WNS = () => {
|
const WNS = () => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const { config } = useContext(ConsoleContext);
|
const { config } = useContext(ConsoleContext);
|
||||||
const data = useQueryStatusReducer(useQuery(QUERY, { pollInterval: config.api.pollInterval }));
|
const data = useQueryStatusReducer(useQuery(WNS_STATUS, { pollInterval: config.api.pollInterval }));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return null;
|
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 (
|
return (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<Json data={{ wns: d }} />
|
<Mutation mutation={WNS_ACTION}>
|
||||||
|
{(action, { data }) => (
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
action({ variables: { command: 'test' } });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Test
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<pre>Result: {JSON.stringify(data)}</pre>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Mutation>
|
||||||
|
|
||||||
|
<Json data={JSON.parse(data.wns_status.json)} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,7 @@ export const createResolvers = config => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
Query: {
|
Query: {
|
||||||
wns: async () => {
|
wns_status: async () => {
|
||||||
log('Querying WNS...');
|
log('Querying WNS...');
|
||||||
|
|
||||||
const status = await registry.getStatus();
|
const status = await registry.getStatus();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"build": {
|
"build": {
|
||||||
"name": "@dxos/console-client",
|
"name": "@dxos/console-client",
|
||||||
"buildDate": "2020-05-24T02:00:10.452Z",
|
"buildDate": "2020-05-24T13:13:49.317Z",
|
||||||
"version": "1.0.0-beta.0"
|
"version": "1.0.0-beta.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,17 +6,36 @@ type JSONResult {
|
|||||||
json: String!
|
json: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Log {
|
||||||
|
log: [String]!
|
||||||
|
}
|
||||||
|
|
||||||
type Status {
|
type Status {
|
||||||
timestamp: String!
|
timestamp: String!
|
||||||
version: String!
|
version: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Result {
|
||||||
|
timestamp: String!
|
||||||
|
code: Int!
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Schema
|
||||||
|
#
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
status: Status
|
system_status: Status
|
||||||
ipfs: JSONResult
|
ipfs_status: JSONResult
|
||||||
wns: JSONResult
|
wns_status: JSONResult
|
||||||
|
wns_log: Log
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mutation {
|
||||||
|
wns_action(command: String!): Result
|
||||||
}
|
}
|
||||||
|
|
||||||
schema {
|
schema {
|
||||||
|
mutation: Mutation
|
||||||
query: Query
|
query: Query
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,9 @@ import yaml from 'js-yaml';
|
|||||||
import { ApolloServer, gql } from 'apollo-server-express';
|
import { ApolloServer, gql } from 'apollo-server-express';
|
||||||
import { print } from 'graphql/language';
|
import { print } from 'graphql/language';
|
||||||
|
|
||||||
import QUERY_STATUS from '@dxos/console-client/gql/status.graphql';
|
import SYSTEM_STATUS from '@dxos/console-client/gql/system_status.graphql';
|
||||||
|
|
||||||
import { resolvers } from './resolvers';
|
import { createResolvers } from './resolvers';
|
||||||
|
|
||||||
import SCHEMA from './gql/api.graphql';
|
import SCHEMA from './gql/api.graphql';
|
||||||
|
|
||||||
@ -60,7 +60,8 @@ app.get(`${publicUrl}(/:filePath)?`, (req, res) => {
|
|||||||
|
|
||||||
const server = new ApolloServer({
|
const server = new ApolloServer({
|
||||||
typeDefs: SCHEMA,
|
typeDefs: SCHEMA,
|
||||||
resolvers,
|
|
||||||
|
resolvers: createResolvers(config),
|
||||||
|
|
||||||
// https://www.apollographql.com/docs/apollo-server/testing/graphql-playground
|
// https://www.apollographql.com/docs/apollo-server/testing/graphql-playground
|
||||||
// https://github.com/prisma-labs/graphql-playground#usage
|
// https://github.com/prisma-labs/graphql-playground#usage
|
||||||
@ -73,7 +74,7 @@ const server = new ApolloServer({
|
|||||||
{
|
{
|
||||||
name: 'Status',
|
name: 'Status',
|
||||||
endpoint: config.api.path,
|
endpoint: config.api.path,
|
||||||
query: print(gql(QUERY_STATUS))
|
query: print(gql(SYSTEM_STATUS))
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -13,13 +13,31 @@ const log = debug('dxos:console:server:resolvers');
|
|||||||
// Resolvers
|
// Resolvers
|
||||||
//
|
//
|
||||||
|
|
||||||
export const resolvers = {
|
const timestamp = () => new Date().toUTCString();
|
||||||
|
|
||||||
|
export const createResolvers = config => ({
|
||||||
|
Mutation: {
|
||||||
|
//
|
||||||
|
// WNS
|
||||||
|
//
|
||||||
|
|
||||||
|
wns_action: async (_, __, { action }) => {
|
||||||
|
log(`WNS action: ${action}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
timestamp: timestamp(),
|
||||||
|
code: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
Query: {
|
Query: {
|
||||||
//
|
//
|
||||||
// Status
|
// System
|
||||||
//
|
//
|
||||||
status: () => ({
|
|
||||||
timestamp: new Date().toUTCString(),
|
system_status: () => ({
|
||||||
|
timestamp: timestamp(),
|
||||||
version
|
version
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@ -29,15 +47,20 @@ export const resolvers = {
|
|||||||
// https://github.com/ipfs/js-ipfs
|
// https://github.com/ipfs/js-ipfs
|
||||||
// https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-http-client#api
|
// https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-http-client#api
|
||||||
//
|
//
|
||||||
ipfs: async () => {
|
|
||||||
|
ipfs_status: async () => {
|
||||||
log('Calling IPFS...');
|
log('Calling IPFS...');
|
||||||
|
|
||||||
// TODO(burdon): Config.
|
// TODO(burdon): Config.
|
||||||
|
// NOTE: Hangs if server not running.
|
||||||
const ipfs = new IpfsHttpClient('/ip4/127.0.0.1/tcp/5001');
|
const ipfs = new IpfsHttpClient('/ip4/127.0.0.1/tcp/5001');
|
||||||
|
|
||||||
const version = await ipfs.version();
|
const version = await ipfs.version();
|
||||||
const status = await ipfs.id();
|
const status = await ipfs.id();
|
||||||
|
|
||||||
|
console.log(version);
|
||||||
|
log('Done');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
json: JSON.stringify({
|
json: JSON.stringify({
|
||||||
version,
|
version,
|
||||||
@ -46,4 +69,4 @@ export const resolvers = {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
11
yarn.lock
11
yarn.lock
@ -29,6 +29,17 @@
|
|||||||
ts-invariant "^0.4.4"
|
ts-invariant "^0.4.4"
|
||||||
tslib "^1.10.0"
|
tslib "^1.10.0"
|
||||||
|
|
||||||
|
"@apollo/react-components@^3.1.5":
|
||||||
|
version "3.1.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@apollo/react-components/-/react-components-3.1.5.tgz#040d2f35ce4947747efe16f76d59dcbd797ffdaf"
|
||||||
|
integrity sha512-c82VyUuE9VBnJB7bnX+3dmwpIPMhyjMwyoSLyQWPHxz8jK4ak30XszJtqFf4eC4hwvvLYa+Ou6X73Q8V8e2/jg==
|
||||||
|
dependencies:
|
||||||
|
"@apollo/react-common" "^3.1.4"
|
||||||
|
"@apollo/react-hooks" "^3.1.5"
|
||||||
|
prop-types "^15.7.2"
|
||||||
|
ts-invariant "^0.4.4"
|
||||||
|
tslib "^1.10.0"
|
||||||
|
|
||||||
"@apollo/react-hooks@^3.1.5":
|
"@apollo/react-hooks@^3.1.5":
|
||||||
version "3.1.5"
|
version "3.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/@apollo/react-hooks/-/react-hooks-3.1.5.tgz#7e710be52461255ae7fc0b3b9c2ece64299c10e6"
|
resolved "https://registry.yarnpkg.com/@apollo/react-hooks/-/react-hooks-3.1.5.tgz#7e710be52461255ae7fc0b3b9c2ece64299c10e6"
|
||||||
|
Loading…
Reference in New Issue
Block a user