chore: initial no style
This commit is contained in:
commit
24f9750e5f
35
actions.js
Normal file
35
actions.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
const {invokeHookSerial} = require('@truss/truss');
|
||||
|
||||
const {Responder} = require('./response.dev');
|
||||
|
||||
const responder = new Responder();
|
||||
|
||||
module.exports = () => ({
|
||||
|
||||
'truss/http-get': (action) => {
|
||||
const {payload: {headers}} = action;
|
||||
|
||||
delete headers.host;
|
||||
delete headers.connection;
|
||||
|
||||
return responder.respond(action).then((html) => {
|
||||
return invokeHookSerial('truss/web-response', {
|
||||
status: 200,
|
||||
headers: defaultHeaders(),
|
||||
html,
|
||||
}, headers);
|
||||
});
|
||||
},
|
||||
|
||||
'truss/schema': () => {
|
||||
return {executors: ['truss/http-get']};
|
||||
},
|
||||
});
|
||||
|
||||
function defaultHeaders() {
|
||||
return {
|
||||
Date: (new Date()).toUTCString(),
|
||||
Connection: 'keep-alive',
|
||||
'Transfer-Encoding': 'chunked',
|
||||
};
|
||||
}
|
4
compose.js
Normal file
4
compose.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
module.exports = (config) => {
|
||||
const backendPort = process.env.PERSEA_BACKPORT || 8004;
|
||||
config.ports = [`${backendPort}:8004`];
|
||||
};
|
10
frontend/index.html
Normal file
10
frontend/index.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Truss</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="root"></div>
|
||||
</body>
|
||||
</html>
|
12
frontend/index.js
Normal file
12
frontend/index.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import Root from './root';
|
||||
import createRootStore from './root/store';
|
||||
|
||||
|
||||
|
||||
ReactDOM.render(
|
||||
<Root store={createRootStore()} />,
|
||||
document.querySelector('.root')
|
||||
);
|
25
frontend/root/app.js
Normal file
25
frontend/root/app.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import classnames from 'classnames';
|
||||
import {Route, Switch} from 'react-router';
|
||||
|
||||
import Welcome from './welcome';
|
||||
function App() {
|
||||
|
||||
return <div className={classnames({
|
||||
app: true,
|
||||
dev: 'production' !== process.env.NODE_ENV,
|
||||
})}>
|
||||
<Switch>
|
||||
<Route path="/" component={Welcome} />
|
||||
</Switch>
|
||||
</div>;
|
||||
}
|
||||
|
||||
import {hot} from 'react-hot-loader';
|
||||
App = hot(module)(App);
|
||||
|
||||
// import {styler} from '@truss/react'
|
||||
// App = styler App, require './app.scss'
|
||||
|
||||
export default App;
|
6
frontend/root/app.scss
Normal file
6
frontend/root/app.scss
Normal file
|
@ -0,0 +1,6 @@
|
|||
.app {
|
||||
background-color: #444444;
|
||||
color: #fff;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
26
frontend/root/dev-tools.js
Normal file
26
frontend/root/dev-tools.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import React from 'react';
|
||||
|
||||
import {createDevTools} from 'redux-devtools';
|
||||
|
||||
import LogMonitor from 'redux-devtools-log-monitor';
|
||||
import DockMonitor from 'redux-devtools-dock-monitor';
|
||||
import FilterMonitor from 'redux-devtools-filter-actions';
|
||||
|
||||
const DevTools = createDevTools(
|
||||
|
||||
<DockMonitor
|
||||
toggleVisibilityKey='ctrl-h'
|
||||
changePositionKey='ctrl-q'
|
||||
>
|
||||
|
||||
<FilterMonitor>
|
||||
|
||||
<LogMonitor
|
||||
theme='tomorrow'
|
||||
/>
|
||||
|
||||
</FilterMonitor>
|
||||
</DockMonitor>
|
||||
);
|
||||
|
||||
export default DevTools;
|
25
frontend/root/index.dev.js
Normal file
25
frontend/root/index.dev.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
import React from 'react';
|
||||
import {Provider} from 'react-redux';
|
||||
import {BrowserRouter} from 'react-router-dom';
|
||||
|
||||
import DevTools from './dev-tools';
|
||||
|
||||
import App from './app';
|
||||
function Root ({store}) {
|
||||
|
||||
return <Provider store={store}>
|
||||
<React.Fragment>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
<div className="dev-tools">
|
||||
<DevTools />
|
||||
</div>
|
||||
</React.Fragment>
|
||||
</Provider>;
|
||||
};
|
||||
|
||||
// import {styler} from '@truss/react'
|
||||
// Root = styler Root, require './index.scss'
|
||||
|
||||
export default Root;
|
7
frontend/root/index.js
Normal file
7
frontend/root/index.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
if ('production' === process.env.NODE_ENV) {
|
||||
module.exports = require('./index.prod');
|
||||
}
|
||||
else {
|
||||
module.exports = require('./index.dev');
|
||||
}
|
18
frontend/root/index.prod.js
Normal file
18
frontend/root/index.prod.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
import React from 'react';
|
||||
import {Provider} from 'react-redux';
|
||||
import {BrowserRouter} from 'react-router-dom';
|
||||
|
||||
import App from './app';
|
||||
function Root ({store}) {
|
||||
|
||||
return <Provider store={store}>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</Provider>;
|
||||
};
|
||||
|
||||
// import {styler} from '@truss/react'
|
||||
// Root = styler Root, require './index.scss'
|
||||
|
||||
export default Root;
|
9
frontend/root/index.scss
Normal file
9
frontend/root/index.scss
Normal file
|
@ -0,0 +1,9 @@
|
|||
@media (max-width: 1023px) {
|
||||
.testing {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.dev-tools {
|
||||
opacity: 0.9;
|
||||
}
|
20
frontend/root/reducer.js
Normal file
20
frontend/root/reducer.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import {combineReducers} from 'redux';
|
||||
import {reducer as formReducer} from 'redux-form/immutable';
|
||||
|
||||
// import {pkgman} from '@truss/core';
|
||||
|
||||
// import {createReducer as createResourceReducer} from '../resource'
|
||||
|
||||
export default function createRootReducer() {
|
||||
|
||||
// dynamicReducers = pkgman.invokeFlat('perseaReducers').reduce(
|
||||
// ((reducers, map) -> {reducers..., map...}), {}
|
||||
// )
|
||||
|
||||
return combineReducers({
|
||||
form: formReducer,
|
||||
// resource: createResourceReducer()
|
||||
|
||||
// dynamicReducers...
|
||||
});
|
||||
}
|
10
frontend/root/saga.js
Normal file
10
frontend/root/saga.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
import {all, call} from 'redux-saga/effects'
|
||||
|
||||
function createRootSaga() {
|
||||
return function*() {
|
||||
return yield all([
|
||||
].map(call));
|
||||
};
|
||||
}
|
||||
|
||||
export default createRootSaga;
|
28
frontend/root/store.dev.js
Normal file
28
frontend/root/store.dev.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
import createSagaMiddleware from 'redux-saga';
|
||||
import {compose, createStore, applyMiddleware} from 'redux';
|
||||
|
||||
import DevTools from './dev-tools';
|
||||
|
||||
import createRootReducer from './reducer';
|
||||
import createRootSaga from './saga';
|
||||
|
||||
export default function createRootStore() {
|
||||
|
||||
const sagaMiddleware = createSagaMiddleware();
|
||||
|
||||
const store = createStore(
|
||||
createRootReducer(),
|
||||
compose(
|
||||
applyMiddleware(sagaMiddleware),
|
||||
DevTools.instrument()
|
||||
)
|
||||
);
|
||||
|
||||
module.hot.accept('./reducer', () => {
|
||||
store.replaceReducer(require('./reducer').default());
|
||||
});
|
||||
|
||||
sagaMiddleware.run(createRootSaga());
|
||||
|
||||
return store;
|
||||
}
|
7
frontend/root/store.js
Normal file
7
frontend/root/store.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
if ('production' === process.env.NODE_ENV) {
|
||||
module.exports = require('./store.prod');
|
||||
}
|
||||
else {
|
||||
module.exports = require('./store.dev');
|
||||
}
|
18
frontend/root/store.prod.js
Normal file
18
frontend/root/store.prod.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
import createSagaMiddleware from 'redux-saga';
|
||||
import {compose, createStore, applyMiddleware} from 'redux';
|
||||
|
||||
import createRootReducer from './reducer';
|
||||
import createRootSaga from './saga';
|
||||
export default function createRootStore() {
|
||||
|
||||
// sagaMiddleware = createSagaMiddleware()
|
||||
|
||||
// store = createStore createRootReducer(), compose(
|
||||
// applyMiddleware sagaMiddleware
|
||||
// )
|
||||
store = createStore(createRootReducer());
|
||||
|
||||
// sagaMiddleware.run(createRootSaga());
|
||||
|
||||
return store
|
||||
}
|
36
frontend/root/welcome.js
Normal file
36
frontend/root/welcome.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
// import {pkgman} from '@truss/core';
|
||||
|
||||
import React from 'react';
|
||||
class Welcome extends React.Component {
|
||||
|
||||
render() {
|
||||
|
||||
return <div className="welcome">
|
||||
<div className="content">
|
||||
<h2>
|
||||
<span>💕 </span>
|
||||
Welcome back to <strong>Persea</strong>
|
||||
<span> 💕</span>
|
||||
</h2>
|
||||
{this.thingsToDo()}
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
thingsToDo() {
|
||||
|
||||
// things = for key, value of pkgman.invoke 'perseaThingsToDo'
|
||||
// <div className={key} key={key}>{value}</div>
|
||||
|
||||
// if things.length is 0
|
||||
const things = <p>You have nothing to do!</p>;
|
||||
|
||||
return <div className="things-to-do">{things}</div>;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// import {styler} from '@truss/react'
|
||||
// Welcome = styler Welcome, require './welcome.scss'
|
||||
|
||||
export default Welcome;
|
27
frontend/root/welcome.scss
Normal file
27
frontend/root/welcome.scss
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
.welcome {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
display: block;
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
|
||||
span {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
background-color: #333;
|
||||
padding: 6em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.things-to-do div {
|
||||
margin-bottom: 1em;
|
||||
}
|
15
index.js
Normal file
15
index.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import {createDispatcher} from '@truss/truss';
|
||||
|
||||
const dispatcher = createDispatcher();
|
||||
dispatcher.lookupActions(require('./actions'));
|
||||
dispatcher.lookupHooks(require('./hooks'));
|
||||
dispatcher.connect();
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.accept('./actions', () => {
|
||||
dispatcher.lookupActions(require('./actions'));
|
||||
});
|
||||
module.hot.accept('./hooks', () => {
|
||||
dispatcher.lookupHooks(require('./hooks'));
|
||||
});
|
||||
}
|
35
package.json
Normal file
35
package.json
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "persea",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "node -e '' -r '@truss/truss/task/build'",
|
||||
"default": "yarn run dev",
|
||||
"dev": "node -e '' -r '@truss/truss/task/scaffold'"
|
||||
},
|
||||
"author": "cha0s",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@truss/truss": "1.x",
|
||||
"classnames": "^2.2.6",
|
||||
"debug": "3.1.0",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"immutable": "^3.8.2",
|
||||
"react": "^16.4.2",
|
||||
"react-dom": "^16.4.2",
|
||||
"react-hot-loader": "^4.3.5",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-router": "^4.3.1",
|
||||
"react-router-dom": "^4.3.1",
|
||||
"redux": "^4.0.0",
|
||||
"redux-devtools": "^3.4.1",
|
||||
"redux-devtools-dock-monitor": "^1.1.3",
|
||||
"redux-devtools-filter-actions": "^1.2.2",
|
||||
"redux-devtools-log-monitor": "^1.4.0",
|
||||
"redux-form": "^7.4.2",
|
||||
"redux-saga": "^0.16.0",
|
||||
"webpack-dev-middleware": "3.1.3",
|
||||
"webpack-hot-middleware": "2.22.3"
|
||||
}
|
||||
}
|
94
response.dev.js
Normal file
94
response.dev.js
Normal file
|
@ -0,0 +1,94 @@
|
|||
|
||||
const http = require('http');
|
||||
|
||||
const webpack = require('webpack');
|
||||
const wdm = require('webpack-dev-middleware');
|
||||
const whm = require('webpack-hot-middleware');
|
||||
|
||||
const debug = require('debug')('truss:persea');
|
||||
|
||||
const {webpackConfig} = require('./webpack.config');
|
||||
|
||||
const backendHostname = process.env.PERSEA_BACKHOST || 'persea';
|
||||
const backendPort = process.env.PERSEA_BACKPORT || 8004;
|
||||
const frontendHostname = process.env.PERSEA_FRONTHOST || 'localhost';
|
||||
|
||||
exports.Responder = class Responder {
|
||||
|
||||
constructor() {
|
||||
const httpServer = this.server = http.createServer();
|
||||
|
||||
httpServer.on('listening', () => {
|
||||
const address = this.address = httpServer.address();
|
||||
const config = webpackConfig();
|
||||
|
||||
config.entry.push(
|
||||
`webpack-hot-middleware/client?path=http://${
|
||||
frontendHostname}:${address.port
|
||||
}/__webpack_hmr`
|
||||
);
|
||||
|
||||
const compiler = webpack(config);
|
||||
this.dm = wdm(compiler, {
|
||||
stats: {
|
||||
chunkModules: true,
|
||||
colors: true,
|
||||
context: process.cwd(),
|
||||
},
|
||||
});
|
||||
this.hm = whm(compiler, {
|
||||
path: '/__webpack_hmr',
|
||||
});
|
||||
|
||||
debug(`HTTP listening on ${JSON.stringify(address)}...`);
|
||||
});
|
||||
|
||||
httpServer.on('request', (req, res) => {
|
||||
this.dm(req, res, (error) => {
|
||||
if (error) {
|
||||
return console.error(error);
|
||||
}
|
||||
this.hm(req, res, (error) => {
|
||||
if (error) {
|
||||
return console.error(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
httpServer.on('error', console.error);
|
||||
|
||||
httpServer.listen(backendPort);
|
||||
}
|
||||
|
||||
respond({payload: {headers, url}}) {
|
||||
headers = Object.assign({}, headers);
|
||||
|
||||
delete headers.host;
|
||||
delete headers.connection;
|
||||
|
||||
// forward to internal HTTP
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
const options = {
|
||||
headers,
|
||||
backendHostname,
|
||||
path: url,
|
||||
port: this.address.port,
|
||||
};
|
||||
|
||||
const client = http.get(options);
|
||||
client.on('response', (res) => {
|
||||
let data = '';
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
client.on('error', reject);
|
||||
});
|
||||
}
|
||||
}
|
0
response.production.js
Normal file
0
response.production.js
Normal file
77
webpack.config.js
Normal file
77
webpack.config.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
const path = require('path');
|
||||
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
|
||||
module.exports = (config) => {
|
||||
|
||||
if ('production' === config.mode) {
|
||||
return [config, module.exports.webpackConfig()];
|
||||
}
|
||||
else {
|
||||
return config;
|
||||
}
|
||||
};
|
||||
|
||||
const SOURCE_PATH = process.env.SOURCE_PATH || '/var/node/src';
|
||||
const OUTPUT_PATH = process.env.OUTPUT_PATH || '/var/node/dist';
|
||||
|
||||
module.exports.webpackConfig = function() {
|
||||
|
||||
const config = {
|
||||
mode: 'production' !== process.env.NODE_ENV ? 'development' : 'production',
|
||||
entry: [
|
||||
'@babel/polyfill',
|
||||
path.join(SOURCE_PATH, 'frontend', 'index.js'),
|
||||
],
|
||||
optimization: {},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /(node_modules|bower_components)/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
babelrcRoots: [
|
||||
OUTPUT_PATH,
|
||||
],
|
||||
plugins: [
|
||||
'@babel/plugin-proposal-object-rest-spread',
|
||||
],
|
||||
presets: [
|
||||
'@babel/preset-react',
|
||||
'@babel/preset-env',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
output: {
|
||||
filename: 'index.js',
|
||||
path: path.join(OUTPUT_PATH, 'frontend'),
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
title: 'Truss',
|
||||
template: path.join(SOURCE_PATH, 'frontend', 'index.html'),
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
modules: [path.join(OUTPUT_PATH, 'node_modules')],
|
||||
}
|
||||
};
|
||||
|
||||
if ('production' === config.mode) {
|
||||
config.optimization.minimizer = [
|
||||
new UglifyJsPlugin({cache: false})
|
||||
];
|
||||
}
|
||||
else {
|
||||
config.plugins.push(new webpack.HotModuleReplacementPlugin());
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
Loading…
Reference in New Issue
Block a user