chore: initial no style

This commit is contained in:
cha0s 2018-09-03 02:03:23 -05:00
commit 24f9750e5f
24 changed files with 545 additions and 0 deletions

35
actions.js Normal file
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,6 @@
.app {
background-color: #444444;
color: #fff;
height: 100%;
width: 100%;
}

View 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;

View 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
View File

@ -0,0 +1,7 @@
if ('production' === process.env.NODE_ENV) {
module.exports = require('./index.prod');
}
else {
module.exports = require('./index.dev');
}

View 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
View File

@ -0,0 +1,9 @@
@media (max-width: 1023px) {
.testing {
margin: 0;
}
}
.dev-tools {
opacity: 0.9;
}

20
frontend/root/reducer.js Normal file
View 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
View File

@ -0,0 +1,10 @@
import {all, call} from 'redux-saga/effects'
function createRootSaga() {
return function*() {
return yield all([
].map(call));
};
}
export default createRootSaga;

View 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
View File

@ -0,0 +1,7 @@
if ('production' === process.env.NODE_ENV) {
module.exports = require('./store.prod');
}
else {
module.exports = require('./store.dev');
}

View 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
View 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;

View 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;
}

1
hooks.js Normal file
View File

@ -0,0 +1 @@
module.exports = () => ({});

15
index.js Normal file
View 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
View 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
View 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
View File

77
webpack.config.js Normal file
View 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;
}