Merge pull request #4 from dxos/burdon/config
Server Console App directly from the server.
This commit is contained in:
commit
8b54937795
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||||
|
</state>
|
||||||
|
</component>
|
@ -7,14 +7,14 @@ Apollo GraphQL client.
|
|||||||
First start the server:
|
First start the server:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd packages/consoe-server
|
cd packages/console-server
|
||||||
yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
|
|
||||||
Then start the Webpack devserver.
|
Then start the Webpack devserver.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd packages/consoe-client
|
cd packages/consoe-app
|
||||||
yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
|
|
@ -8,6 +8,10 @@ module.exports = {
|
|||||||
'@babel/preset-react'
|
'@babel/preset-react'
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
|
// Allows export of components importing GQL files (without webpack).
|
||||||
|
'import-graphql',
|
||||||
|
'inline-json-import',
|
||||||
|
|
||||||
'@babel/plugin-proposal-class-properties',
|
'@babel/plugin-proposal-class-properties',
|
||||||
'@babel/plugin-proposal-export-default-from'
|
'@babel/plugin-proposal-export-default-from'
|
||||||
]
|
]
|
41
packages/console-app/config.yml
Normal file
41
packages/console-app/config.yml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#
|
||||||
|
# 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
|
||||||
|
intervalLog: 5000
|
||||||
|
pollInterval: 10000
|
||||||
|
|
||||||
|
system:
|
||||||
|
debug: 'dxos:console:*'
|
||||||
|
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
prefix: '/app'
|
||||||
|
server: 'http://127.0.0.1:5999'
|
||||||
|
|
||||||
|
wns:
|
||||||
|
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'
|
||||||
|
|
||||||
|
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'
|
@ -1,18 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "@dxos/console-client",
|
"name": "@dxos/console-app",
|
||||||
"version": "1.0.0-beta.0",
|
"version": "1.0.0-beta.0",
|
||||||
"description": "DxOS Console Client",
|
"description": "DxOS Console Client",
|
||||||
"main": "dist/es/index.js",
|
"main": "dist/es/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
"config.yml",
|
"src/gql"
|
||||||
"dist/production",
|
|
||||||
"gql"
|
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"analyzer": "webpack --config webpack-analyzer.config.js",
|
"analyzer": "webpack --config webpack-analyzer.config.js",
|
||||||
"build": "npm run clean && npm run build:module && npm run build:production",
|
"build": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --source-maps inline",
|
||||||
"build:module": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --source-maps inline",
|
|
||||||
"build:production": "PUBLIC_URL=/console webpack --mode production",
|
|
||||||
"clean": "rm -rf dist",
|
"clean": "rm -rf dist",
|
||||||
"lint": "semistandard 'src/**/*.js'",
|
"lint": "semistandard 'src/**/*.js'",
|
||||||
"start": "VERBOSE=true webpack-dev-server --mode development",
|
"start": "VERBOSE=true webpack-dev-server --mode development",
|
||||||
@ -47,9 +43,6 @@
|
|||||||
"graphql-tag": "^2.10.3",
|
"graphql-tag": "^2.10.3",
|
||||||
"lodash.defaultsdeep": "^4.6.1",
|
"lodash.defaultsdeep": "^4.6.1",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"lodash.isobject": "^3.0.2",
|
|
||||||
"lodash.omit": "^4.5.0",
|
|
||||||
"lodash.transform": "^4.6.0",
|
|
||||||
"moment": "^2.26.0",
|
"moment": "^2.26.0",
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
@ -69,7 +62,9 @@
|
|||||||
"babel-jest": "^24.8.0",
|
"babel-jest": "^24.8.0",
|
||||||
"babel-loader": "^8.0.0",
|
"babel-loader": "^8.0.0",
|
||||||
"babel-plugin-add-module-exports": "^1.0.2",
|
"babel-plugin-add-module-exports": "^1.0.2",
|
||||||
|
"babel-plugin-import-graphql": "^2.7.0",
|
||||||
"babel-plugin-inline-import": "^3.0.0",
|
"babel-plugin-inline-import": "^3.0.0",
|
||||||
|
"babel-plugin-inline-json-import": "^0.3.2",
|
||||||
"dotenv-webpack": "^1.8.0",
|
"dotenv-webpack": "^1.8.0",
|
||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
"eslint-config-semistandard": "^15.0.0",
|
"eslint-config-semistandard": "^15.0.0",
|
||||||
@ -94,6 +89,10 @@
|
|||||||
"webpack-version-file-plugin": "^0.4.0",
|
"webpack-version-file-plugin": "^0.4.0",
|
||||||
"yaml-loader": "^0.6.0"
|
"yaml-loader": "^0.6.0"
|
||||||
},
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "16.12.0",
|
||||||
|
"react-dom": "^16.12.0"
|
||||||
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
26
packages/console-app/src/components/Json.js
Normal file
26
packages/console-app/src/components/Json.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DxOS.org
|
||||||
|
//
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { makeStyles } from '@material-ui/core';
|
||||||
|
|
||||||
|
import { JsonTreeView } from '@dxos/react-ux';
|
||||||
|
|
||||||
|
import { omitDeep } from '../util/omit';
|
||||||
|
|
||||||
|
const useStyles = makeStyles(() => ({
|
||||||
|
root: {
|
||||||
|
flex: 1
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
const Json = ({ data }) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<JsonTreeView className={classes.root} data={omitDeep(data, '__typename')} />
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Json;
|
@ -2,7 +2,6 @@
|
|||||||
// Copyright 2020 DxOS.org
|
// Copyright 2020 DxOS.org
|
||||||
//
|
//
|
||||||
|
|
||||||
import debug from 'debug';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { HashRouter, Redirect, Route, Switch } from 'react-router-dom';
|
import { HashRouter, Redirect, Route, Switch } from 'react-router-dom';
|
||||||
import { ApolloProvider } from '@apollo/react-hooks';
|
import { ApolloProvider } from '@apollo/react-hooks';
|
||||||
@ -11,11 +10,10 @@ import CssBaseline from '@material-ui/core/CssBaseline';
|
|||||||
|
|
||||||
import { ErrorHandler } from '@dxos/debug';
|
import { ErrorHandler } from '@dxos/debug';
|
||||||
|
|
||||||
import config from '../../config.yml';
|
import { build } from '../version.json';
|
||||||
import { build } from '../../version.json';
|
|
||||||
|
|
||||||
import { createTheme } from '../theme';
|
|
||||||
import { clientFactory } from '../client';
|
import { clientFactory } from '../client';
|
||||||
|
import { createTheme } from '../theme';
|
||||||
import modules from '../modules';
|
import modules from '../modules';
|
||||||
|
|
||||||
import Layout from './Layout';
|
import Layout from './Layout';
|
||||||
@ -30,18 +28,15 @@ import Signaling from './panels/Signaling';
|
|||||||
import Status from './panels/Status';
|
import Status from './panels/Status';
|
||||||
import WNS from './panels/wns/WNS';
|
import WNS from './panels/wns/WNS';
|
||||||
|
|
||||||
// TODO(burdon): Config object.
|
|
||||||
Object.assign(config, { build });
|
|
||||||
|
|
||||||
debug.enable(config.system.debug);
|
|
||||||
|
|
||||||
// Global error handler.
|
// Global error handler.
|
||||||
const errorHandler = new ErrorHandler();
|
const errorHandler = new ErrorHandler();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root application.
|
* Root application.
|
||||||
*/
|
*/
|
||||||
const Main = () => {
|
const Main = ({ config }) => {
|
||||||
|
Object.assign(config, { build });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ApolloProvider client={clientFactory(config)}>
|
<ApolloProvider client={clientFactory(config)}>
|
||||||
<ConsoleContextProvider config={config} modules={modules} errorHandler={errorHandler}>
|
<ConsoleContextProvider config={config} modules={modules} errorHandler={errorHandler}>
|
@ -7,8 +7,8 @@ import React, { useEffect, useState } from 'react';
|
|||||||
import { useQuery } from '@apollo/react-hooks';
|
import { useQuery } from '@apollo/react-hooks';
|
||||||
import { makeStyles } from '@material-ui/core';
|
import { makeStyles } from '@material-ui/core';
|
||||||
|
|
||||||
import SYSTEM_STATUS from '../../gql/system_status.graphql';
|
import SYSTEM_STATUS from '../gql/system_status.graphql';
|
||||||
import WNS_RECORDS from '../../gql/wns_records.graphql';
|
import WNS_RECORDS from '../gql/wns_records.graphql';
|
||||||
|
|
||||||
import { useQueryStatusReducer } from '../hooks';
|
import { useQueryStatusReducer } from '../hooks';
|
||||||
|
|
||||||
@ -35,9 +35,10 @@ const VersionCheck = () => {
|
|||||||
// Check version.
|
// Check version.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (status && data) {
|
if (status && data) {
|
||||||
const { dxos: { image: current } } = JSON.parse(status.system_status.json);
|
const { dxos: { image: current } } = status.system_status;
|
||||||
let latest = current;
|
let latest = current;
|
||||||
data.wns_records.json.forEach(({ attributes: { name, version } }) => {
|
data.wns_records.json.forEach(({ attributes: { name, version } }) => {
|
||||||
|
// 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) {
|
||||||
latest = version;
|
latest = version;
|
@ -7,7 +7,7 @@ import { useQuery } from '@apollo/react-hooks';
|
|||||||
|
|
||||||
import Json from '../../components/Json';
|
import Json from '../../components/Json';
|
||||||
|
|
||||||
import SYSTEM_STATUS from '../../../gql/system_status.graphql';
|
import SYSTEM_STATUS from '../../gql/system_status.graphql';
|
||||||
|
|
||||||
import { ConsoleContext, useQueryStatusReducer } from '../../hooks';
|
import { ConsoleContext, useQueryStatusReducer } from '../../hooks';
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ const Status = () => {
|
|||||||
<Toolbar />
|
<Toolbar />
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Json data={JSON.parse(data.system_status.json)} />
|
<Json data={data.system_status} />
|
||||||
</Panel>
|
</Panel>
|
||||||
);
|
);
|
||||||
};
|
};
|
@ -5,7 +5,7 @@
|
|||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { useQuery } from '@apollo/react-hooks';
|
import { useQuery } from '@apollo/react-hooks';
|
||||||
|
|
||||||
import WNS_RECORDS from '../../../../gql/wns_records.graphql';
|
import WNS_RECORDS from '../../../gql/wns_records.graphql';
|
||||||
|
|
||||||
import { ConsoleContext, useQueryStatusReducer, useSorter } from '../../../hooks';
|
import { ConsoleContext, useQueryStatusReducer, useSorter } from '../../../hooks';
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { useQuery } from '@apollo/react-hooks';
|
import { useQuery } from '@apollo/react-hooks';
|
||||||
|
|
||||||
import WNS_RECORDS from '../../../../gql/wns_records.graphql';
|
import WNS_RECORDS from '../../../gql/wns_records.graphql';
|
||||||
|
|
||||||
import { ConsoleContext, useQueryStatusReducer, useSorter } from '../../../hooks';
|
import { ConsoleContext, useQueryStatusReducer, useSorter } from '../../../hooks';
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useQuery } from '@apollo/react-hooks';
|
import { useQuery } from '@apollo/react-hooks';
|
||||||
|
|
||||||
import IPFS_STATUS from '../../../../gql/ipfs_status.graphql';
|
import IPFS_STATUS from '../../../gql/ipfs_status.graphql';
|
||||||
|
|
||||||
import { useQueryStatusReducer } from '../../../hooks';
|
import { useQueryStatusReducer } from '../../../hooks';
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { useQuery } from '@apollo/react-hooks';
|
import { useQuery } from '@apollo/react-hooks';
|
||||||
|
|
||||||
import WNS_LOG from '../../../../gql/wns_log.graphql';
|
import WNS_LOG from '../../../gql/wns_log.graphql';
|
||||||
|
|
||||||
import { ConsoleContext, useQueryStatusReducer } from '../../../hooks';
|
import { ConsoleContext, useQueryStatusReducer } from '../../../hooks';
|
||||||
|
|
@ -13,7 +13,7 @@ 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 WNS_RECORDS from '../../../../gql/wns_records.graphql';
|
import WNS_RECORDS from '../../../gql/wns_records.graphql';
|
||||||
|
|
||||||
import { ConsoleContext, useQueryStatusReducer, useSorter } from '../../../hooks';
|
import { ConsoleContext, useQueryStatusReducer, useSorter } from '../../../hooks';
|
||||||
|
|
||||||
@ -26,9 +26,10 @@ const types = [
|
|||||||
{ key: null, label: 'ALL' },
|
{ key: null, label: 'ALL' },
|
||||||
{ key: 'wrn:xbox', label: 'XBox' },
|
{ key: 'wrn:xbox', label: 'XBox' },
|
||||||
{ key: 'wrn:resource', label: 'Resource' },
|
{ key: 'wrn:resource', label: 'Resource' },
|
||||||
|
{ key: 'wrn:service', label: 'Service' },
|
||||||
{ key: 'wrn:app', label: 'App' },
|
{ key: 'wrn:app', label: 'App' },
|
||||||
{ key: 'wrn:bot', label: 'Bot' },
|
{ key: 'wrn:bot', label: 'Bot' },
|
||||||
{ key: 'wrn:type', label: 'Type' },
|
{ key: 'wrn:type', label: 'Type' }
|
||||||
];
|
];
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => ({
|
const useStyles = makeStyles(theme => ({
|
@ -5,7 +5,7 @@
|
|||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { useQuery } from '@apollo/react-hooks';
|
import { useQuery } from '@apollo/react-hooks';
|
||||||
|
|
||||||
import WNS_STATUS from '../../../../gql/wns_status.graphql';
|
import WNS_STATUS from '../../../gql/wns_status.graphql';
|
||||||
|
|
||||||
import { ConsoleContext, useQueryStatusReducer } from '../../../hooks';
|
import { ConsoleContext, useQueryStatusReducer } from '../../../hooks';
|
||||||
|
|
@ -2,7 +2,7 @@
|
|||||||
# Copyright 2020 DxOS.org
|
# Copyright 2020 DxOS.org
|
||||||
#
|
#
|
||||||
|
|
||||||
{
|
query {
|
||||||
ipfs_status {
|
ipfs_status {
|
||||||
json
|
json
|
||||||
}
|
}
|
21
packages/console-app/src/gql/system_status.graphql
Normal file
21
packages/console-app/src/gql/system_status.graphql
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2020 DxOS.org
|
||||||
|
#
|
||||||
|
|
||||||
|
query {
|
||||||
|
system_status {
|
||||||
|
timestamp
|
||||||
|
dxos {
|
||||||
|
image
|
||||||
|
}
|
||||||
|
system {
|
||||||
|
network {
|
||||||
|
address
|
||||||
|
}
|
||||||
|
nodejs {
|
||||||
|
version
|
||||||
|
environment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
# Copyright 2020 DxOS.org
|
# Copyright 2020 DxOS.org
|
||||||
#
|
#
|
||||||
|
|
||||||
{
|
query {
|
||||||
wns_log @client {
|
wns_log @client {
|
||||||
timestamp
|
timestamp
|
||||||
log
|
log
|
@ -2,7 +2,7 @@
|
|||||||
# Copyright 2020 DxOS.org
|
# Copyright 2020 DxOS.org
|
||||||
#
|
#
|
||||||
|
|
||||||
{
|
query {
|
||||||
wns_status @client {
|
wns_status @client {
|
||||||
timestamp
|
timestamp
|
||||||
json
|
json
|
@ -29,11 +29,11 @@ export const useQueryStatusReducer = ({ loading, error, data }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
setTimeout(() => setStatus({ loading }));
|
setStatus({ loading });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
setTimeout(() => setStatus({ error }));
|
setStatus({ error });
|
||||||
}
|
}
|
||||||
}, [loading, error]);
|
}, [loading, error]);
|
||||||
|
|
9
packages/console-app/src/index.js
Normal file
9
packages/console-app/src/index.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DxOS.org
|
||||||
|
//
|
||||||
|
|
||||||
|
import Main from './containers/Main';
|
||||||
|
|
||||||
|
export {
|
||||||
|
Main
|
||||||
|
};
|
15
packages/console-app/src/main.js
Normal file
15
packages/console-app/src/main.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DxOS.org
|
||||||
|
//
|
||||||
|
|
||||||
|
import debug from 'debug';
|
||||||
|
import React from 'react';
|
||||||
|
import { render } from 'react-dom';
|
||||||
|
|
||||||
|
import config from '../config.yml';
|
||||||
|
|
||||||
|
import Main from './containers/Main';
|
||||||
|
|
||||||
|
debug.enable(config.system.debug);
|
||||||
|
|
||||||
|
render(<Main config={config} />, document.getElementById('root'));
|
@ -59,19 +59,15 @@ export const createResolvers = config => {
|
|||||||
wns_log: async () => {
|
wns_log: async () => {
|
||||||
log('WNS log...');
|
log('WNS log...');
|
||||||
|
|
||||||
const data = await registry.getLogs();
|
|
||||||
|
|
||||||
// TODO(burdon): Bug returns blank line at end.
|
|
||||||
const filtered = data.map(line => line).filter(Boolean);
|
|
||||||
|
|
||||||
// Cache and merge previous state.
|
// Cache and merge previous state.
|
||||||
let i = filtered.findIndex(line => line === cachedLog[cachedLog.length - 1]);
|
const data = await registry.getLogs();
|
||||||
|
let i = data.findIndex(line => line === cachedLog[cachedLog.length - 1]);
|
||||||
if (i === -1) {
|
if (i === -1) {
|
||||||
cachedLog = filtered;
|
cachedLog = data;
|
||||||
} else {
|
} else {
|
||||||
i++;
|
i++;
|
||||||
for (; i < filtered.length - 1; i++) {
|
for (; i < data.length - 1; i++) {
|
||||||
cachedLog.push(filtered[i]);
|
cachedLog.push(data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trim.
|
// Trim.
|
22
packages/console-app/src/util/omit.js
Normal file
22
packages/console-app/src/util/omit.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DxOS.org
|
||||||
|
//
|
||||||
|
|
||||||
|
// TODO(burdon): Factor out.
|
||||||
|
export const omitDeep = (value, key) => {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map(i => omitDeep(i, key));
|
||||||
|
} else if (typeof value === 'object' && value !== null) {
|
||||||
|
return Object.keys(value).reduce((newObject, k) => {
|
||||||
|
if (k === key) {
|
||||||
|
return newObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.assign({
|
||||||
|
[k]: omitDeep(value[k], key),
|
||||||
|
}, newObject);
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
};
|
7
packages/console-app/src/version.json
Normal file
7
packages/console-app/src/version.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"name": "@dxos/console-app",
|
||||||
|
"buildDate": "2020-05-27T22:04:52.661Z",
|
||||||
|
"version": "1.0.0-beta.0"
|
||||||
|
}
|
||||||
|
}
|
@ -9,10 +9,10 @@ const webpack = require('webpack');
|
|||||||
|
|
||||||
const PUBLIC_URL = process.env.PUBLIC_URL || '';
|
const PUBLIC_URL = process.env.PUBLIC_URL || '';
|
||||||
|
|
||||||
|
// TODO(burdon): Remove.
|
||||||
const STACK_CONFIG = process.env.CONFIG || 'default';
|
const STACK_CONFIG = process.env.CONFIG || 'default';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
devtool: 'eval-source-map',
|
devtool: 'eval-source-map',
|
||||||
|
|
||||||
devServer: {
|
devServer: {
|
||||||
@ -30,7 +30,6 @@ module.exports = {
|
|||||||
fs: 'empty'
|
fs: 'empty'
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO(burdon): Config production path for apollo (diff webpack config).
|
|
||||||
output: {
|
output: {
|
||||||
path: `${__dirname}/dist/production`,
|
path: `${__dirname}/dist/production`,
|
||||||
filename: '[name].bundle.js',
|
filename: '[name].bundle.js',
|
||||||
@ -74,9 +73,6 @@ module.exports = {
|
|||||||
// NOTE: Must be defined below Dotenv (otherwise will override).
|
// NOTE: Must be defined below Dotenv (otherwise will override).
|
||||||
// https://webpack.js.org/plugins/environment-plugin
|
// https://webpack.js.org/plugins/environment-plugin
|
||||||
new webpack.EnvironmentPlugin({
|
new webpack.EnvironmentPlugin({
|
||||||
PUBLIC_URL: String(PUBLIC_URL),
|
|
||||||
STACK_CONFIG: String(STACK_CONFIG),
|
|
||||||
DEBUG: ''
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Define the build config file based on the target.
|
// Define the build config file based on the target.
|
||||||
@ -87,14 +83,14 @@ module.exports = {
|
|||||||
|
|
||||||
// https://www.npmjs.com/package/webpack-version-file-plugin
|
// https://www.npmjs.com/package/webpack-version-file-plugin
|
||||||
new VersionFile({
|
new VersionFile({
|
||||||
|
template: path.join(__dirname, 'version.ejs'),
|
||||||
packageFile: path.join(__dirname, 'package.json'),
|
packageFile: path.join(__dirname, 'package.json'),
|
||||||
outputFile: path.join(__dirname, 'version.json')
|
outputFile: path.join(__dirname, 'src', 'version.json')
|
||||||
}),
|
})
|
||||||
],
|
],
|
||||||
|
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
// js
|
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
exclude: /(node_modules)/,
|
exclude: /(node_modules)/,
|
||||||
@ -108,27 +104,6 @@ module.exports = {
|
|||||||
test: /\.ya?ml$/,
|
test: /\.ya?ml$/,
|
||||||
type: 'json',
|
type: 'json',
|
||||||
use: 'yaml-loader'
|
use: 'yaml-loader'
|
||||||
},
|
|
||||||
|
|
||||||
// https://www.apollographql.com/docs/react/integrations/webpack
|
|
||||||
{
|
|
||||||
test: /\.(graphql|gql)$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
loader: 'graphql-tag/loader'
|
|
||||||
},
|
|
||||||
|
|
||||||
// fonts
|
|
||||||
{
|
|
||||||
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: 'file-loader',
|
|
||||||
options: {
|
|
||||||
name: '[name].[ext]',
|
|
||||||
outputPath: 'fonts/'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
@ -8,8 +8,7 @@ const HtmlWebPackPlugin = require('html-webpack-plugin');
|
|||||||
const commonConfig = require('./webpack-common.config');
|
const commonConfig = require('./webpack-common.config');
|
||||||
|
|
||||||
module.exports = merge(commonConfig, {
|
module.exports = merge(commonConfig, {
|
||||||
|
entry: './src/main.js',
|
||||||
entry: './src/main',
|
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
// https://github.com/jantimon/html-webpack-plugin#options
|
// https://github.com/jantimon/html-webpack-plugin#options
|
@ -1,10 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright 2020 DxOS.org
|
|
||||||
#
|
|
||||||
|
|
||||||
{
|
|
||||||
system_status {
|
|
||||||
timestamp
|
|
||||||
json
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2020 DxOS.org
|
|
||||||
//
|
|
||||||
|
|
||||||
import isObject from 'lodash.isobject';
|
|
||||||
import omit from 'lodash.omit';
|
|
||||||
import transform from 'lodash.transform';
|
|
||||||
import React from 'react';
|
|
||||||
import { makeStyles } from '@material-ui/core';
|
|
||||||
|
|
||||||
import { JsonTreeView } from '@dxos/react-ux';
|
|
||||||
|
|
||||||
const useStyles = makeStyles(() => ({
|
|
||||||
root: {
|
|
||||||
flex: 1
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove Apollo __typename directive.
|
|
||||||
* @param {Object} data
|
|
||||||
* @returns {Object}
|
|
||||||
*/
|
|
||||||
const removeTypename = data => transform(data, (result, value, key) => {
|
|
||||||
if (key !== '__typename') {
|
|
||||||
result[key] = isObject(value) ? ('__typename' in value ? omit(value, '__typename') : value) : value;
|
|
||||||
}
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
const Json = ({ data }) => {
|
|
||||||
const classes = useStyles();
|
|
||||||
|
|
||||||
// TODO(burdon): Bug expands when updated.
|
|
||||||
return (
|
|
||||||
<JsonTreeView className={classes.root} data={removeTypename(data)} />
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Json;
|
|
@ -1,5 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2020 DxOS.org
|
|
||||||
//
|
|
||||||
|
|
||||||
export * from './hooks';
|
|
@ -1,10 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2020 DxOS.org
|
|
||||||
//
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import { render } from 'react-dom';
|
|
||||||
|
|
||||||
import Main from './containers/Main';
|
|
||||||
|
|
||||||
render(<Main />, document.getElementById('root'));
|
|
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"build": {
|
|
||||||
"name": "@dxos/console-client",
|
|
||||||
"buildDate": "2020-05-27T01:16:27.565Z",
|
|
||||||
"version": "1.0.0-beta.0"
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,9 +4,41 @@ Apollo GraphQL client.
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
Use the following command to run the server at: http://localhost:4000
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn
|
|
||||||
yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
|
|
||||||
http://localhost:4000
|
To test the Console app, the `@dxos/console-app` must be built first:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ../console-app
|
||||||
|
yarn build
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the following command to run the client in development mode (via the `webpack-dev-server`) at http://localhost:8080
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn dev
|
||||||
|
```
|
||||||
|
|
||||||
|
To build the client and serve it directly from the server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn build
|
||||||
|
yarn start
|
||||||
|
```
|
||||||
|
|
||||||
|
Then open the app at: http://localhost:4000/console
|
||||||
|
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
When running the Console server, either set the `CONFIG_FILE` environment variable or set the `--config` option.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/console.js --config ./config.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: The server passes its configuration directly to the Console app when it is loaded.
|
||||||
|
@ -4,20 +4,23 @@
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
presets: [
|
presets: [
|
||||||
[
|
'@babel/preset-env',
|
||||||
'@babel/preset-env'
|
'@babel/preset-react'
|
||||||
]
|
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
[
|
[
|
||||||
'babel-plugin-inline-import', {
|
'babel-plugin-inline-import', {
|
||||||
extensions: [
|
extensions: [
|
||||||
'.graphql',
|
'.mustache',
|
||||||
'.proto',
|
'.graphql'
|
||||||
'.txt'
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// Allows export of components importing GQL files (without webpack).
|
||||||
|
'import-graphql',
|
||||||
|
'inline-json-import',
|
||||||
|
|
||||||
'@babel/plugin-proposal-class-properties',
|
'@babel/plugin-proposal-class-properties',
|
||||||
'@babel/plugin-proposal-export-default-from'
|
'@babel/plugin-proposal-export-default-from'
|
||||||
]
|
]
|
||||||
|
3
packages/console-server/bin/console.js
Executable file
3
packages/console-server/bin/console.js
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
module.exports = require('../dist/es/server/main.js');
|
@ -3,6 +3,8 @@
|
|||||||
# NOTE: Set CONFIG_FILE to swap out this config file.
|
# NOTE: Set CONFIG_FILE to swap out this config file.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# TODO(burdon): Set defaults.
|
||||||
|
|
||||||
app:
|
app:
|
||||||
title: 'Console'
|
title: 'Console'
|
||||||
org': 'DxOS'
|
org': 'DxOS'
|
||||||
@ -18,23 +20,19 @@ api:
|
|||||||
|
|
||||||
system:
|
system:
|
||||||
debug: 'dxos:console:*'
|
debug: 'dxos:console:*'
|
||||||
xbox:
|
|
||||||
image: '/opt/xbox/IMAGE'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
prefix: '/app'
|
prefix: '/app'
|
||||||
server: 'http://127.0.0.1:5999' # TODO(burdon): ???
|
server: 'http://127.0.0.1:5999'
|
||||||
|
|
||||||
wns:
|
wns:
|
||||||
server: 'https://node1.dxos.network/wns/api'
|
server: 'https://node1.dxos.network/wns/api'
|
||||||
webui: 'https://node1.dxos.network/wns/webui'
|
webui: 'https://node1.dxos.network/wns/webui'
|
||||||
# server: 'http://127.0.0.1:9473/api'
|
|
||||||
# webui: 'http://127.0.0.1:9473/webui'
|
|
||||||
|
|
||||||
signal:
|
signal:
|
||||||
server: 'http://127.0.0.1:4000'
|
server: 'http://127.0.0.1:4000'
|
||||||
api: 'http://127.0.0.1:4000' # TODO(burdon): ???
|
api: 'http://127.0.0.1:4000'
|
||||||
|
|
||||||
ipfs:
|
ipfs:
|
||||||
server: '/ip4/127.0.0.1/tcp/5001'
|
server: '/ip4/127.0.0.1/tcp/5001'
|
@ -1,12 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "@dxos/console-server",
|
"name": "@dxos/console",
|
||||||
"version": "1.0.0-beta.0",
|
"version": "1.0.0-beta.0",
|
||||||
"description": "DxOS Console Server",
|
"description": "DxOS Console Server",
|
||||||
"main": "index.js",
|
"main": "dist/es/index.js",
|
||||||
|
"bin": {
|
||||||
|
"console": "bin/console.js"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"bin/",
|
||||||
|
"dist/es"
|
||||||
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"build": "npm run clean && npm run build:client && npm run build:server",
|
||||||
|
"build:client": "PUBLIC_URL=/console webpack --mode development",
|
||||||
|
"build:server": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --copy-files",
|
||||||
|
"clean": "rm -rf ./dist",
|
||||||
|
"dev": "VERBOSE=true webpack-dev-server --mode development --watch",
|
||||||
"lint": "semistandard 'src/**/*.js'",
|
"lint": "semistandard 'src/**/*.js'",
|
||||||
"test": "jest --rootDir ./src --passWithNoTests --no-cache",
|
"test": "jest --rootDir ./src --passWithNoTests --no-cache",
|
||||||
"start": "BABEL_DISABLE_CACHE=1 nodemon --exec babel-node ./src/main.js"
|
"start": "CONFIG_FILE=./config.yml BABEL_DISABLE_CACHE=1 nodemon --exec babel-node src/server/main.js -- --verbose"
|
||||||
},
|
},
|
||||||
"author": "DxOS.org",
|
"author": "DxOS.org",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
@ -17,8 +29,10 @@
|
|||||||
"testEnvironment": "node"
|
"testEnvironment": "node"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/polyfill": "^7.8.7",
|
||||||
"@babel/runtime": "^7.8.7",
|
"@babel/runtime": "^7.8.7",
|
||||||
"@dxos/console-client": "^1.0.0-beta.0",
|
"@dxos/console-app": "^1.0.0-beta.0",
|
||||||
|
"@wirelineio/wns-schema": "^0.1.1",
|
||||||
"apollo-boost": "^0.4.9",
|
"apollo-boost": "^0.4.9",
|
||||||
"apollo-server-express": "^2.13.1",
|
"apollo-server-express": "^2.13.1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
@ -26,10 +40,17 @@
|
|||||||
"express-graphql": "^0.9.0",
|
"express-graphql": "^0.9.0",
|
||||||
"graphql": "^15.0.0",
|
"graphql": "^15.0.0",
|
||||||
"graphql-tag": "^2.10.3",
|
"graphql-tag": "^2.10.3",
|
||||||
|
"graphql-tools": "^6.0.3",
|
||||||
"ipfs-http-client": "^44.1.0",
|
"ipfs-http-client": "^44.1.0",
|
||||||
"js-yaml": "^3.14.0",
|
"js-yaml": "^3.14.0",
|
||||||
|
"lodash.defaultsdeep": "^4.6.1",
|
||||||
|
"lodash.pick": "^4.4.0",
|
||||||
|
"mustache-express": "^1.3.0",
|
||||||
|
"react": "^16.13.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
"source-map-support": "^0.5.12"
|
"source-map-support": "^0.5.12",
|
||||||
|
"systeminformation": "^4.26.5",
|
||||||
|
"yargs": "^15.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "7.4.4",
|
"@babel/cli": "7.4.4",
|
||||||
@ -40,8 +61,14 @@
|
|||||||
"@babel/preset-env": "^7.4.5",
|
"@babel/preset-env": "^7.4.5",
|
||||||
"babel-eslint": "^10.0.3",
|
"babel-eslint": "^10.0.3",
|
||||||
"babel-jest": "^24.8.0",
|
"babel-jest": "^24.8.0",
|
||||||
|
"babel-loader": "^8.1.0",
|
||||||
"babel-plugin-add-module-exports": "^1.0.2",
|
"babel-plugin-add-module-exports": "^1.0.2",
|
||||||
|
"babel-plugin-import-graphql": "^2.7.0",
|
||||||
"babel-plugin-inline-import": "^3.0.0",
|
"babel-plugin-inline-import": "^3.0.0",
|
||||||
|
"babel-plugin-inline-json-import": "^0.3.2",
|
||||||
|
"body-parser": "^1.19.0",
|
||||||
|
"compression": "^1.7.4",
|
||||||
|
"dotenv-webpack": "^1.8.0",
|
||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
"eslint-config-semistandard": "^15.0.0",
|
"eslint-config-semistandard": "^15.0.0",
|
||||||
"eslint-config-standard": "^14.1.1",
|
"eslint-config-standard": "^14.1.1",
|
||||||
@ -54,7 +81,13 @@
|
|||||||
"eslint-plugin-standard": "^4.0.1",
|
"eslint-plugin-standard": "^4.0.1",
|
||||||
"jest": "^24.8.0",
|
"jest": "^24.8.0",
|
||||||
"nodemon": "^2.0.4",
|
"nodemon": "^2.0.4",
|
||||||
"semistandard": "^14.2.0"
|
"react": "^16.13.1",
|
||||||
|
"react-dom": "^16.13.1",
|
||||||
|
"semistandard": "^14.2.0",
|
||||||
|
"webpack": "^4.41.2",
|
||||||
|
"webpack-cli": "^3.3.10",
|
||||||
|
"webpack-dev-server": "^3.11.0",
|
||||||
|
"webpack-merge": "^4.2.2"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
10
packages/console-server/public/index.html
Normal file
10
packages/console-server/public/index.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title><%= title %></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
16
packages/console-server/src/client/main.js
Normal file
16
packages/console-server/src/client/main.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DxOS.org
|
||||||
|
//
|
||||||
|
|
||||||
|
import debug from 'debug';
|
||||||
|
import React from 'react';
|
||||||
|
import { render } from 'react-dom';
|
||||||
|
|
||||||
|
import { Main } from '@dxos/console-app';
|
||||||
|
|
||||||
|
// Load from global printed into HTML page via template.
|
||||||
|
const { config } = window.__DXOS__;
|
||||||
|
|
||||||
|
debug.enable(config.system.debug);
|
||||||
|
|
||||||
|
render(<Main config={config} />, document.getElementById('root'));
|
@ -2,6 +2,12 @@
|
|||||||
# Copyright 2020 DxOS.org
|
# Copyright 2020 DxOS.org
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# TODO(burdon): Replace generic results with schema.
|
||||||
|
type JSONResult {
|
||||||
|
timestamp: String!
|
||||||
|
json: String!
|
||||||
|
}
|
||||||
|
|
||||||
type Result {
|
type Result {
|
||||||
timestamp: String!
|
timestamp: String!
|
||||||
code: Int!
|
code: Int!
|
||||||
@ -12,27 +18,20 @@ type Log {
|
|||||||
log: [String]!
|
log: [String]!
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO(burdon): Generic result.
|
|
||||||
type JSONResult {
|
|
||||||
timestamp: String!
|
|
||||||
json: String!
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Schema
|
# Schema
|
||||||
#
|
#
|
||||||
|
|
||||||
type Query {
|
type Mutation {
|
||||||
system_status: JSONResult!
|
action(command: String!): Result!
|
||||||
ipfs_status: JSONResult!
|
|
||||||
wns_status: JSONResult!
|
|
||||||
# TODO(burdon): Import WNS schema!
|
|
||||||
wns_records(type: String): JSONResult!
|
|
||||||
wns_log: Log!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Query {
|
||||||
wns_action(command: String!): Result!
|
system_status: SystemStatus!
|
||||||
|
ipfs_status: JSONResult!
|
||||||
|
wns_status: JSONResult!
|
||||||
|
wns_records(type: String): JSONResult!
|
||||||
|
wns_log: Log!
|
||||||
}
|
}
|
||||||
|
|
||||||
schema {
|
schema {
|
||||||
|
27
packages/console-server/src/gql/system.graphql
Normal file
27
packages/console-server/src/gql/system.graphql
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#
|
||||||
|
# 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 {
|
||||||
|
timestamp: String!
|
||||||
|
dxos: DXOSInfo
|
||||||
|
system: SystemInfo
|
||||||
|
}
|
@ -1,101 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2020 DxOS.org
|
|
||||||
//
|
|
||||||
|
|
||||||
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 SYSTEM_STATUS from '@dxos/console-client/gql/system_status.graphql';
|
|
||||||
|
|
||||||
import { createResolvers } 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');
|
|
||||||
|
|
||||||
debug.enable(config.system.debug);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Express server.
|
|
||||||
//
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
|
|
||||||
//
|
|
||||||
// CORS
|
|
||||||
//
|
|
||||||
|
|
||||||
// import cors from 'cors'
|
|
||||||
// https://expressjs.com/en/resources/middleware/cors.html
|
|
||||||
// https://www.prisma.io/blog/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d
|
|
||||||
// app.use(cors({
|
|
||||||
// origin: true,
|
|
||||||
// credentials: true
|
|
||||||
// }));
|
|
||||||
|
|
||||||
//
|
|
||||||
// React app
|
|
||||||
//
|
|
||||||
|
|
||||||
const { app: { publicUrl } } = config;
|
|
||||||
|
|
||||||
// TODO(burdon): Load via WNS.
|
|
||||||
app.get(`${publicUrl}(/:filePath)?`, (req, res) => {
|
|
||||||
const { filePath = 'index.html' } = req.params;
|
|
||||||
const file = path.join(__dirname, '../../../node_modules/@dxos/console-client/dist/production', filePath);
|
|
||||||
res.sendFile(file);
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
|
||||||
// Apollo Server
|
|
||||||
// https://www.apollographql.com/docs/apollo-server/api/apollo-server
|
|
||||||
//
|
|
||||||
|
|
||||||
const server = new ApolloServer({
|
|
||||||
typeDefs: SCHEMA,
|
|
||||||
|
|
||||||
resolvers: createResolvers(config),
|
|
||||||
|
|
||||||
// https://www.apollographql.com/docs/apollo-server/testing/graphql-playground
|
|
||||||
// https://github.com/prisma-labs/graphql-playground#usage
|
|
||||||
// introspection: true,
|
|
||||||
playground: {
|
|
||||||
settings: {
|
|
||||||
'editor.theme': 'light'
|
|
||||||
},
|
|
||||||
tabs: [
|
|
||||||
{
|
|
||||||
name: 'Status',
|
|
||||||
endpoint: config.api.path,
|
|
||||||
query: print(gql(SYSTEM_STATUS))
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
|
||||||
// Apollo middleware
|
|
||||||
// https://www.apollographql.com/docs/apollo-server/api/apollo-server/#apolloserverapplymiddleware
|
|
||||||
//
|
|
||||||
|
|
||||||
server.applyMiddleware({
|
|
||||||
app,
|
|
||||||
path: config.api.path
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
|
||||||
// Start server
|
|
||||||
//
|
|
||||||
|
|
||||||
const { api: { port } } = config;
|
|
||||||
app.listen({ port }, () => {
|
|
||||||
log(`Running: http://localhost:${port}`);
|
|
||||||
});
|
|
@ -1,82 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2020 DxOS.org
|
|
||||||
//
|
|
||||||
|
|
||||||
import debug from 'debug';
|
|
||||||
import IpfsHttpClient from 'ipfs-http-client';
|
|
||||||
|
|
||||||
const log = debug('dxos:console:server:resolvers');
|
|
||||||
|
|
||||||
const timestamp = () => new Date().toUTCString();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolvers
|
|
||||||
* https://www.apollographql.com/docs/graphql-tools/resolvers
|
|
||||||
* @param config
|
|
||||||
*/
|
|
||||||
export const createResolvers = config => ({
|
|
||||||
|
|
||||||
// TODO(burdon): Auth mutations.
|
|
||||||
// https://www.apollographql.com/docs/apollo-server/data/errors/#codes
|
|
||||||
|
|
||||||
Mutation: {
|
|
||||||
//
|
|
||||||
// WNS
|
|
||||||
//
|
|
||||||
|
|
||||||
wns_action: async (_, { command }) => {
|
|
||||||
log(`WNS action: ${command}`);
|
|
||||||
|
|
||||||
return {
|
|
||||||
timestamp: timestamp(),
|
|
||||||
code: 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Query: {
|
|
||||||
//
|
|
||||||
// System
|
|
||||||
//
|
|
||||||
|
|
||||||
// TODO(burdon): System calls.
|
|
||||||
system_status: () => {
|
|
||||||
return {
|
|
||||||
timestamp: timestamp(),
|
|
||||||
json: JSON.stringify({
|
|
||||||
dxos: {
|
|
||||||
image: '0.0.1'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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_status: async () => {
|
|
||||||
log('Calling IPFS...');
|
|
||||||
|
|
||||||
// TODO(burdon): Config.
|
|
||||||
// NOTE: Hangs if server not running.
|
|
||||||
const ipfs = new IpfsHttpClient('/ip4/127.0.0.1/tcp/5001');
|
|
||||||
|
|
||||||
const version = await ipfs.version();
|
|
||||||
const status = await ipfs.id();
|
|
||||||
|
|
||||||
console.log(version);
|
|
||||||
log('Done');
|
|
||||||
|
|
||||||
return {
|
|
||||||
json: JSON.stringify({
|
|
||||||
version,
|
|
||||||
status
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
32
packages/console-server/src/resolvers/index.js
Normal file
32
packages/console-server/src/resolvers/index.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DxOS.org
|
||||||
|
//
|
||||||
|
|
||||||
|
import debug from 'debug';
|
||||||
|
import defaultsDeep from 'lodash.defaultsdeep';
|
||||||
|
|
||||||
|
import { ipfsResolvers } from './ipfs';
|
||||||
|
import { systemResolvers } from './system';
|
||||||
|
|
||||||
|
const log = debug('dxos:console:server:resolvers');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolvers
|
||||||
|
* https://www.apollographql.com/docs/graphql-tools/resolvers
|
||||||
|
*/
|
||||||
|
export const resolvers = defaultsDeep({
|
||||||
|
|
||||||
|
// TODO(burdon): Auth.
|
||||||
|
// https://www.apollographql.com/docs/apollo-server/data/errors/#codes
|
||||||
|
|
||||||
|
Mutation: {
|
||||||
|
action: async (_, { command }) => {
|
||||||
|
log(`WNS action: ${command}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
timestamp: new Date().toUTCString(),
|
||||||
|
code: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, ipfsResolvers, systemResolvers);
|
36
packages/console-server/src/resolvers/ipfs.js
Normal file
36
packages/console-server/src/resolvers/ipfs.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DxOS.org
|
||||||
|
//
|
||||||
|
|
||||||
|
import debug from 'debug';
|
||||||
|
import IpfsHttpClient from 'ipfs-http-client';
|
||||||
|
const log = debug('dxos:console:server:resolvers');
|
||||||
|
|
||||||
|
export const ipfsResolvers = {
|
||||||
|
Query: {
|
||||||
|
//
|
||||||
|
// 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_status: async (_, __, { config }) => {
|
||||||
|
log('Calling IPFS...');
|
||||||
|
|
||||||
|
// NOTE: Hangs if server not running.
|
||||||
|
const ipfs = new IpfsHttpClient(config.services.ipfs.server);
|
||||||
|
|
||||||
|
const version = await ipfs.version();
|
||||||
|
const status = await ipfs.id();
|
||||||
|
|
||||||
|
return {
|
||||||
|
timestamp: new Date().toUTCString(),
|
||||||
|
json: JSON.stringify({
|
||||||
|
version,
|
||||||
|
status
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
91
packages/console-server/src/resolvers/system.js
Normal file
91
packages/console-server/src/resolvers/system.js
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DxOS.org
|
||||||
|
//
|
||||||
|
|
||||||
|
import moment from 'moment';
|
||||||
|
import pick from 'lodash.pick';
|
||||||
|
import os from 'os';
|
||||||
|
import si from 'systeminformation';
|
||||||
|
|
||||||
|
const num = new Intl.NumberFormat('en', { maximumSignificantDigits: 3 });
|
||||||
|
|
||||||
|
const size = (n, unit) => {
|
||||||
|
const units = {
|
||||||
|
K: 3,
|
||||||
|
M: 6,
|
||||||
|
G: 9,
|
||||||
|
T: 12
|
||||||
|
};
|
||||||
|
|
||||||
|
const power = units[unit] || 0;
|
||||||
|
|
||||||
|
return num.format(Math.round(n / (10 ** power))) + (unit ? ` ${unit}` : '');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get system inforamtion.
|
||||||
|
* https://www.npmjs.com/package/systeminformation
|
||||||
|
*/
|
||||||
|
const getSystemInfo = async () => {
|
||||||
|
const ifaces = os.networkInterfaces();
|
||||||
|
const addresses = Object.entries(ifaces).reduce((result, [, values]) => {
|
||||||
|
values.forEach(({ family, address }) => {
|
||||||
|
if (family === 'IPv4' && address !== '127.0.0.1') {
|
||||||
|
result.push(address);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const cpu = await si.cpu();
|
||||||
|
const memory = await si.mem();
|
||||||
|
const device = await si.system();
|
||||||
|
|
||||||
|
return {
|
||||||
|
cpu: pick(cpu, 'brand', 'cores', 'manufacturer', 'vendor'),
|
||||||
|
|
||||||
|
memory: {
|
||||||
|
total: size(memory.total, 'M'),
|
||||||
|
free: size(memory.free, 'M'),
|
||||||
|
used: size(memory.used, 'M'),
|
||||||
|
swaptotal: size(memory.swaptotal, 'M')
|
||||||
|
},
|
||||||
|
|
||||||
|
device: pick(device, 'model', 'serial', 'version'),
|
||||||
|
|
||||||
|
network: {
|
||||||
|
address: addresses
|
||||||
|
},
|
||||||
|
|
||||||
|
// https://nodejs.org/api/os.html
|
||||||
|
os: {
|
||||||
|
arch: os.arch(),
|
||||||
|
type: os.type(),
|
||||||
|
platform: os.platform(),
|
||||||
|
version: os.version ? os.version() : undefined, // Node > 13
|
||||||
|
uptime: moment().subtract(os.uptime(), 'seconds').fromNow()
|
||||||
|
},
|
||||||
|
|
||||||
|
nodejs: {
|
||||||
|
version: process.version,
|
||||||
|
environment: process.env.NODE_ENV
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const systemResolvers = {
|
||||||
|
Query: {
|
||||||
|
system_status: async () => {
|
||||||
|
const system = await getSystemInfo();
|
||||||
|
|
||||||
|
return {
|
||||||
|
timestamp: new Date().toUTCString(),
|
||||||
|
dxos: {
|
||||||
|
// TODO(burdon): ???
|
||||||
|
image: '0.0.1'
|
||||||
|
},
|
||||||
|
system
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
159
packages/console-server/src/server/main.js
Normal file
159
packages/console-server/src/server/main.js
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2020 DxOS.org
|
||||||
|
//
|
||||||
|
|
||||||
|
import compression from 'compression';
|
||||||
|
import bodyParser from 'body-parser';
|
||||||
|
import cors from 'cors';
|
||||||
|
import debug from 'debug';
|
||||||
|
import express from 'express';
|
||||||
|
import mustache from 'mustache-express';
|
||||||
|
import fs from 'fs';
|
||||||
|
import yaml from 'js-yaml';
|
||||||
|
import { ApolloServer, gql } from 'apollo-server-express';
|
||||||
|
import { print } from 'graphql/language';
|
||||||
|
import yargs from 'yargs';
|
||||||
|
|
||||||
|
// TODO(burdon): Use once published by @ashwinp.
|
||||||
|
// import { extensions as WNS_EXTENSIONS, schema as WNS_SCHEMA } from '@wirelineio/wns-schema';
|
||||||
|
|
||||||
|
import SYSTEM_STATUS from '@dxos/console-app/src/gql/system_status.graphql';
|
||||||
|
|
||||||
|
import { resolvers } from '../resolvers';
|
||||||
|
|
||||||
|
import API_SCHEMA from '../gql/api.graphql';
|
||||||
|
import SYSTEM_SCHEMA from '../gql/system.graphql';
|
||||||
|
|
||||||
|
const argv = yargs
|
||||||
|
.option('config', {
|
||||||
|
alias: 'c',
|
||||||
|
description: 'Config file',
|
||||||
|
type: 'string'
|
||||||
|
})
|
||||||
|
.option('verbose', {
|
||||||
|
alias: 'v',
|
||||||
|
description: 'Verbse info',
|
||||||
|
type: 'boolean'
|
||||||
|
})
|
||||||
|
.help()
|
||||||
|
.alias('help', 'h')
|
||||||
|
.argv;
|
||||||
|
|
||||||
|
const configFile = argv.config || process.env.CONFIG_FILE;
|
||||||
|
if (!configFile) {
|
||||||
|
yargs.showHelp();
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = yaml.safeLoad(fs.readFileSync(configFile));
|
||||||
|
|
||||||
|
const log = debug('dxos:console:server');
|
||||||
|
|
||||||
|
debug.enable(config.system.debug);
|
||||||
|
|
||||||
|
if (argv.verbose) {
|
||||||
|
log(JSON.stringify(config, undefined, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Express server.
|
||||||
|
//
|
||||||
|
|
||||||
|
const { app: { publicUrl } } = config;
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
app.set('views', `${__dirname}/views`);
|
||||||
|
app.set('view engine', 'mustache');
|
||||||
|
app.engine('mustache', mustache());
|
||||||
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
app.use(compression());
|
||||||
|
|
||||||
|
app.get('/', (req, res) => {
|
||||||
|
res.redirect(publicUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// CORS
|
||||||
|
//
|
||||||
|
|
||||||
|
// import cors from 'cors'
|
||||||
|
// https://expressjs.com/en/resources/middleware/cors.html
|
||||||
|
// https://www.prisma.io/blog/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d
|
||||||
|
app.use(cors({
|
||||||
|
origin: true,
|
||||||
|
credentials: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
//
|
||||||
|
// React app
|
||||||
|
// TODO(burdon): Can we load this via WNS?
|
||||||
|
//
|
||||||
|
|
||||||
|
const bundles = [
|
||||||
|
'runtime', 'vendor', 'material-ui', 'dxos', 'main'
|
||||||
|
];
|
||||||
|
|
||||||
|
app.use(`${publicUrl}/lib`, express.static('./dist/client'));
|
||||||
|
|
||||||
|
app.get(publicUrl, (req, res) => {
|
||||||
|
res.render('console', {
|
||||||
|
title: 'Console',
|
||||||
|
container: 'root',
|
||||||
|
config: JSON.stringify(config),
|
||||||
|
scripts: bundles.map(bundle => ({ src: `${publicUrl}/lib/${bundle}.bundle.js` }))
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Apollo Server and middleware
|
||||||
|
// https://www.apollographql.com/docs/apollo-server/api/apollo-server
|
||||||
|
// https://www.apollographql.com/docs/apollo-server/api/apollo-server/#apolloserverapplymiddleware
|
||||||
|
//
|
||||||
|
|
||||||
|
const server = new ApolloServer({
|
||||||
|
typeDefs: [
|
||||||
|
API_SCHEMA,
|
||||||
|
SYSTEM_SCHEMA
|
||||||
|
// WNS_EXTENSIONS,
|
||||||
|
// WNS_SCHEMA
|
||||||
|
],
|
||||||
|
|
||||||
|
// https://www.apollographql.com/docs/graphql-tools/resolvers
|
||||||
|
resolvers,
|
||||||
|
|
||||||
|
// https://www.apollographql.com/docs/apollo-server/data/resolvers/#the-context-argument
|
||||||
|
context: ({ req }) => ({
|
||||||
|
config,
|
||||||
|
|
||||||
|
// TODO(burdon): Auth.
|
||||||
|
authToken: req.headers.authorization
|
||||||
|
}),
|
||||||
|
|
||||||
|
// https://www.apollographql.com/docs/apollo-server/testing/graphql-playground
|
||||||
|
// https://github.com/prisma-labs/graphql-playground#usage
|
||||||
|
// introspection: true,
|
||||||
|
playground: {
|
||||||
|
settings: {
|
||||||
|
'editor.theme': config.app.theme
|
||||||
|
},
|
||||||
|
tabs: [
|
||||||
|
{
|
||||||
|
name: 'Status',
|
||||||
|
endpoint: config.api.path,
|
||||||
|
query: print(gql(SYSTEM_STATUS))
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.applyMiddleware({ app, path: config.api.path });
|
||||||
|
|
||||||
|
//
|
||||||
|
// Start server
|
||||||
|
//
|
||||||
|
|
||||||
|
const { api: { port } } = config;
|
||||||
|
app.listen({ port }, () => {
|
||||||
|
log(`Running: http://localhost:${port}`);
|
||||||
|
});
|
20
packages/console-server/src/server/views/console.mustache
Normal file
20
packages/console-server/src/server/views/console.mustache
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="{{ container }}"></div>
|
||||||
|
|
||||||
|
<!-- Config loaded by client. -->
|
||||||
|
<script charset="utf-8" type="application/javascript">
|
||||||
|
window.__DXOS__ = { config: {{{ config }}} };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- React bundles. -->
|
||||||
|
{{#scripts}}
|
||||||
|
<script charset="utf-8" type="application/javascript" src="{{src}}"></script>
|
||||||
|
{{/scripts}}
|
||||||
|
</body>
|
||||||
|
</html>
|
110
packages/console-server/webpack.config.js
Normal file
110
packages/console-server/webpack.config.js
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2019 DxOS
|
||||||
|
//
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const Dotenv = require('dotenv-webpack');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const HtmlWebPackPlugin = require('html-webpack-plugin');
|
||||||
|
|
||||||
|
const PUBLIC_URL = process.env.PUBLIC_URL || '';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
devtool: 'eval-source-map',
|
||||||
|
|
||||||
|
devServer: {
|
||||||
|
contentBase: path.join(__dirname, 'dist'),
|
||||||
|
compress: true,
|
||||||
|
disableHostCheck: true,
|
||||||
|
port: 8080,
|
||||||
|
watchOptions: {
|
||||||
|
ignored: /node_modules/,
|
||||||
|
aggregateTimeout: 600
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
node: {
|
||||||
|
fs: 'empty'
|
||||||
|
},
|
||||||
|
|
||||||
|
entry: './src/client/main.js',
|
||||||
|
|
||||||
|
output: {
|
||||||
|
path: `${__dirname}/dist/client`,
|
||||||
|
filename: '[name].bundle.js',
|
||||||
|
publicPath: PUBLIC_URL
|
||||||
|
},
|
||||||
|
|
||||||
|
optimization: {
|
||||||
|
runtimeChunk: 'single',
|
||||||
|
splitChunks: {
|
||||||
|
chunks: 'all',
|
||||||
|
maxInitialRequests: Infinity,
|
||||||
|
minSize: 0,
|
||||||
|
cacheGroups: {
|
||||||
|
vendor: {
|
||||||
|
test: /[\\/]node_modules[\\/]/,
|
||||||
|
name (module) {
|
||||||
|
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
|
||||||
|
|
||||||
|
if (packageName.startsWith('@dxos')) {
|
||||||
|
return 'dxos';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packageName.startsWith('@material-ui')) {
|
||||||
|
return 'material-ui';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'vendor';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
// https://github.com/jantimon/html-webpack-plugin#options
|
||||||
|
new HtmlWebPackPlugin({
|
||||||
|
template: './public/index.html',
|
||||||
|
templateParameters: {
|
||||||
|
title: 'DxOS Console'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
// https://www.npmjs.com/package/dotenv-webpack#properties
|
||||||
|
new Dotenv({
|
||||||
|
path: process.env.DOT_ENV || '.env'
|
||||||
|
}),
|
||||||
|
|
||||||
|
// NOTE: Must be defined below Dotenv (otherwise will override).
|
||||||
|
// https://webpack.js.org/plugins/environment-plugin
|
||||||
|
new webpack.EnvironmentPlugin({})
|
||||||
|
],
|
||||||
|
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
exclude: /(node_modules)/,
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// https://github.com/eemeli/yaml-loader
|
||||||
|
{
|
||||||
|
test: /\.ya?ml$/,
|
||||||
|
type: 'json',
|
||||||
|
use: 'yaml-loader'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@material-ui/styles': path.resolve(__dirname, '..', '..', 'node_modules/@material-ui/styles'),
|
||||||
|
'react': path.resolve(__dirname, '..', '..', 'node_modules/react'),
|
||||||
|
'react-dom': path.resolve(__dirname, '..', '..', 'node_modules/react-dom')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user