Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jsjaspreet committed Feb 21, 2017
0 parents commit b932b4f
Show file tree
Hide file tree
Showing 30 changed files with 5,108 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"presets": ["env", "stage-1", "react"],
"plugins": ["transform-class-properties", "syntax-dynamic-import"]
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea
node_modules
build
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# React Starter

Web starter project powered by React, Node.js, GraphQL. Webpack2 config for both client and server, Docker for deployment, Postgres backed persistence.

## Prerequisites
- Docker, Docker Compose
- Node v6
- Yarn

## Running the app

Install dependencies and bring up hot-reloading environment for quick development

```
yarn
npm run dev
```

## Postgres with Docker (for scaffolded graphql endpoints)

Build the expected Docker container, bring it up using compose, and run bootstrap scripts for migrations

```
cd postgres
./build.sh
cd ..
docker-compose up -d
(wait for pg to boot)
./bootstrap.sh
```


## NPM Scripts

Helper Scripts

| script | effect |
|--------------|--------------------------------------------------------------------------------------------|
| dev | Build both server and client, HMR activates on client side and Nodemon restarts server on change
| build:prod | Build production assets
|
4 changes: 4 additions & 0 deletions bootstrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
docker exec postgres-starter /bin/bash -c "psql -U postgres links < schema.sql"
docker exec postgres-starter /bin/bash -c "psql -U postgres links < seed.sql"
export NODE_ENV="development"
67 changes: 67 additions & 0 deletions client.webpack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const webpack = require('webpack')
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const WebpackMd5Hash = require('webpack-md5-hash')

const vendor_libs = [
'react', 'babel-polyfill', 'react-dom', 'react-router-dom'
]

let plugins = [
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
}),
new WebpackMd5Hash(),
new HtmlWebpackPlugin({
template: 'src/server/index.html',
title: 'Starter Project',
favicon: './favicon.ico'
})
]

if (process.env.NODE_ENV === 'production') {
plugins = [...plugins,
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false
})]
}


module.exports = {
entry: {
bundle: ['babel-polyfill', './src/client/index.js'],
vendor: vendor_libs
},
output: {
path: path.join(__dirname, 'build'),
filename: '[chunkhash].[id].[name].js',
publicPath: process.env.NODE_ENV === 'dev' ? '' : '/build/'
},
module: {
rules: [
{
use: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/
},
{
use: ['style-loader', 'css-loader'],
test: /\.css$/
}
]
},
devtool: 'cheap-module-source-map',
plugins: plugins,
devServer: {
proxy: {
"/api": "http://localhost:9090",
"/graphql": "http://localhost:9090"
}
}
}
36 changes: 36 additions & 0 deletions database/pgdb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import humps from 'humps'

export default (pgPool) => {
return {
getLinks() {
return pgPool.query(`
select * from links
`).then(res => humps.camelizeKeys(res.rows))
},
addLink({ link, linkTitle, createdAt }) {
return pgPool.query(`
insert into links("link", "link_title", "created_at")
values
($1, $2, $3)
returning *
`, [link, linkTitle, createdAt]).then(res => {
return humps.camelizeKeys(res.rows[0])
})
},
deleteLink({ id }) {
return pgPool.query(`
delete from links where id=$1
returning *
`, [id]).then(res => humps.camelizeKeys(res.rows[0]))
},
updateLink({ id, link, linkTitle }) {
return pgPool.query(`
update links
set link=$1,
link_title=$2
where id=$3
returning *
`, [link, linkTitle, id]).then(res => humps.camelizeKeys(res.rows[0]))
}
}
}
11 changes: 11 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: "2"

services:
postgres_starter:
image: postgres:starter
container_name: "postgres-starter"
ports:
- 5432:5432
environment:
- POSTGRES_DB=links

Binary file added favicon.ico
Binary file not shown.
54 changes: 54 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "new-starter",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "npm run clean && npm run build:client && npm run build:server",
"build:prod": "export NODE_ENV=production && npm run clean && npm run build:client-prod && npm run build:server",
"build:server": "webpack --config server.webpack.js",
"watch:server": "webpack -w --config server.webpack.js & nodemon build/server.js",
"build:client": "webpack --config client.webpack.js",
"build:client-prod": "export NODE_ENV=production && webpack -p --config client.webpack.js",
"dev": "npm run clean && export NODE_ENV=dev && webpack-dev-server --config client.webpack.js & npm run watch:server",
"clean": "rimraf build"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.23.1",
"babel-loader": "^6.3.2",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-class-properties": "^6.23.0",
"babel-polyfill": "^6.23.0",
"babel-preset-env": "^1.1.8",
"babel-preset-react": "^6.23.0",
"babel-preset-stage-1": "^6.22.0",
"css-loader": "^0.26.1",
"html-webpack-plugin": "^2.28.0",
"nodemon": "^1.11.0",
"rimraf": "^2.6.0",
"style-loader": "^0.13.1",
"webpack": "2",
"webpack-dev-server": "^2.4.0",
"webpack-md5-hash": "^0.0.5",
"webpack-node-externals": "^1.5.4"
},
"dependencies": {
"axios": "^0.15.3",
"compression": "^1.6.2",
"express": "^4.14.1",
"express-graphql": "^0.6.3",
"graphql": "^0.9.1",
"graphql-relay": "^0.5.1",
"humps": "^2.0.0",
"lodash": "^4.17.4",
"moment": "^2.17.1",
"pg": "^6.1.2",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-router-dom": "next"
}
}
4 changes: 4 additions & 0 deletions postgres/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM postgres:9.6

ADD schema.sql /
ADD seed.sql /
2 changes: 2 additions & 0 deletions postgres/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
docker build -t postgres:starter .
6 changes: 6 additions & 0 deletions postgres/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
development: {
database: 'links',
user: 'postgres'
}
}
6 changes: 6 additions & 0 deletions postgres/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
create table links (
id serial primary key,
link varchar(255) not null,
link_title varchar(255) not null,
created_at timestamp not null
);
9 changes: 9 additions & 0 deletions postgres/seed.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
insert into "links" (
"link",
"link_title",
"created_at")
values
('https://reacttraining.com/react-router/','React Router','2017-01-08 04:05:06 -8:00'),
('https://facebook.github.io/relay/','Relay Docs','2017-01-09 05:28:33 -8:00'),
('http://exploringjs.com/es6/index.html','Exploring ES6','2017-01-10 06:35:38 -8:00'),
('https://www.postgresql.org/docs/9.6/static/datatype-datetime.html','Postgres Date Type','2017-01-11 02:01:19 -8:00');
22 changes: 22 additions & 0 deletions schema/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
GraphQLSchema,
GraphQLObjectType
} from 'graphql'

import storeType from './types/store'
import mutations from './mutations'

const RootSchema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: () => ({
store: {
type: storeType,
resolve: () => ({})
}
})
}),
mutation: mutations
})

export default RootSchema
40 changes: 40 additions & 0 deletions schema/mutations/addLink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {
GraphQLNonNull,
GraphQLString
} from 'graphql'

import {
mutationWithClientMutationId
} from 'graphql-relay'

import moment from 'moment'

import pgPool from '../../src/server/pgPool'
import pgdbCreator from '../../database/pgdb'
import LinkConnectionType from '../types/linkConnection'
import storeType from '../types/store'

const AddLinkMutation = mutationWithClientMutationId({
name: 'AddLink',
inputFields: {
link: { type: new GraphQLNonNull(GraphQLString) },
linkTitle: { type: new GraphQLNonNull(GraphQLString) },
},
outputFields: {
link: {
type: LinkConnectionType.edgeType,
resolve: (obj) => ({ node: obj, cursor: obj.id })
},
store: {
type: storeType,
resolve: () => ({})
}
},
mutateAndGetPayload: (input) => {
const pgdb = pgdbCreator(pgPool)
const createdAt = moment().toISOString()
return pgdb.addLink({ ...input, createdAt })
}
})

export default AddLinkMutation
41 changes: 41 additions & 0 deletions schema/mutations/deleteLink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {
GraphQLNonNull,
GraphQLString,
GraphQLID
} from 'graphql'

import {
mutationWithClientMutationId
} from 'graphql-relay'

import pgPool from '../../src/server/pgPool'
import pgdbCreator from '../../database/pgdb'
import LinkConnectionType from '../types/linkConnection'
import storeType from '../types/store'

const deleteLinkMutation = mutationWithClientMutationId({
name: 'DeleteLink',
inputFields: {
id: { type: new GraphQLNonNull(GraphQLID) },
},
outputFields: {
deletedLinkId: {
type: GraphQLString,
resolve: (obj) => obj.id
},
link: {
type: LinkConnectionType.edgeType,
resolve: (obj) => ({ node: obj, cursor: obj.id })
},
store: {
type: storeType,
resolve: () => ({})
}
},
mutateAndGetPayload: (input) => {
const pgdb = pgdbCreator(pgPool)
return pgdb.deleteLink(input)
}
})

export default deleteLinkMutation
19 changes: 19 additions & 0 deletions schema/mutations/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {
GraphQLObjectType
} from 'graphql'

import CreateLinkMutation from './addLink'
import DeleteLinkMutation from './deleteLink'
import UpdateLinkMutation from './updateLink'

const RootMutationType = new GraphQLObjectType({
name: 'RootMutationType',
fields: () => ({
AddLink: CreateLinkMutation,
DeleteLink: DeleteLinkMutation,
UpdateLink: UpdateLinkMutation
})
})

export default RootMutationType

Loading

0 comments on commit b932b4f

Please sign in to comment.