Version 1.0.0.

Initial release.
This commit is contained in:
Jayden Seric 2017-04-02 23:14:11 +10:00
commit aa63c4c500
21 changed files with 473 additions and 0 deletions

11
.editorconfig Normal file
View File

@ -0,0 +1,11 @@
# http://EditorConfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
node_modules
*.log
yarn.lock
.env
.DS_Store

2
api/.env.example Normal file
View File

@ -0,0 +1,2 @@
NODE_ENV=development
PORT=3001

1
api/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/dist

4
api/config.js Normal file
View File

@ -0,0 +1,4 @@
import path from 'path'
export const distPath = path.resolve(__dirname, 'dist')
export const apiEndpoint = '/graphql'

58
api/package.json Normal file
View File

@ -0,0 +1,58 @@
{
"name": "apollo-upload-examples-api",
"private": true,
"dependencies": {
"apollo-upload-server": "^2.0.0",
"babel-core": "^6.24.0",
"babel-loader": "^7.0.0-beta.1",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-0": "^6.22.0",
"graphql": "^0.9.2",
"graphql-server-koa": "^0.6.0",
"graphql-tag": "^2.0.0",
"graphql-tools": "^0.11.0",
"kcors": "^2.2.1",
"koa": "^2.2.0",
"koa-bodyparser": "^4.2.0",
"koa-compress": "^2.0.0",
"koa-router": "^7.1.1",
"source-map-support": "^0.4.14",
"webpack": "^2.3.2",
"zoo": "^0.1.9"
},
"devDependencies": {
"babel-cli": "^6.24.0",
"babel-eslint": "^7.2.1",
"chalk": "^1.1.3",
"indent-string": "^3.1.0",
"standard": "^9.0.2"
},
"scripts": {
"lint": "standard",
"dev": "zoo babel-node scripts/dev",
"build": "zoo webpack",
"start": "zoo node dist"
},
"engines": {
"node": ">=7.6"
},
"babel": {
"presets": [
[
"env",
{
"targets": {
"node": 7.6
}
}
],
"stage-0"
]
},
"standard": {
"parser": "babel-eslint",
"ignore": [
"dist/**"
]
}
}

17
api/readme.md Normal file
View File

@ -0,0 +1,17 @@
# Apollo upload examples API
An example GraphQL API using [Apollo upload server](https://github.com/jaydenseric/apollo-upload-server).
## Setup
1. Install the latest [Node.js](https://nodejs.org).
2. Run `npm install` within the `api` directory in Terminal.
3. Copy `.env.example`, rename it `.env` and customize.
For development run `npm run dev`.
For production run `npm run build && npm run start`.
## Support
- Node.js versions >= 7.6.

13
api/resolvers.js Normal file
View File

@ -0,0 +1,13 @@
export default {
Query: {
ignore () {
return null
}
},
Mutation: {
singleUpload (root, {file}) {
console.log('Uploaded file:', file)
return file
}
}
}

22
api/schema.graphql Normal file
View File

@ -0,0 +1,22 @@
type File {
name: String!
type: String!
size: Int!
path: String!
}
input Upload {
name: String!
type: String!
size: Int!
path: String!
}
type Query {
# GraphQL will not work without defining a query.
ignore: Boolean
}
type Mutation {
singleUpload (file: Upload!): File!
}

49
api/scripts/dev.js Normal file
View File

@ -0,0 +1,49 @@
import 'source-map-support/register'
import {spawn} from 'child_process'
import chalk from 'chalk'
import indentString from 'indent-string'
import webpack from 'webpack'
import webpackConfig from '../webpack.config.babel'
let serverProcess
let wasServerMessage
function startServer () {
serverProcess = spawn('node', [webpackConfig.output.path])
serverProcess.stdout.on('data', data => {
console.log((wasServerMessage ? '' : '\n') + indentString(chalk.white(data), 4))
wasServerMessage = true
})
serverProcess.stderr.on('data', data => {
console.error((wasServerMessage ? '' : '\n') + indentString(chalk.red(data), 4))
wasServerMessage = true
})
}
function stopServer () {
if (serverProcess) serverProcess.kill()
}
const compiler = webpack(webpackConfig)
const watcher = compiler.watch({}, (errors, stats) => {
const hasErrors = errors || stats.hasErrors()
console[hasErrors ? 'error' : 'log']((stats.toString('minimal')))
wasServerMessage = false
stopServer()
if (!hasErrors) startServer()
})
function exit () {
watcher.close()
stopServer()
}
;[
'SIGINT',
'SIGTERM',
'SIGHUP',
'SIGQUIT',
'exit',
'uncaughtException'
].forEach(event => process.on(event, exit))

45
api/server.js Normal file
View File

@ -0,0 +1,45 @@
import 'source-map-support/register'
import Koa from 'koa'
import cors from 'kcors'
import compress from 'koa-compress'
import KoaRouter from 'koa-router'
import koaBody from 'koa-bodyparser'
import {makeExecutableSchema} from 'graphql-tools'
import {graphqlKoa} from 'graphql-server-koa'
import {apolloUploadKoa} from 'apollo-upload-server'
import {apiEndpoint} from './config'
import typeDefs from './schema.graphql'
import resolvers from './resolvers'
const app = new Koa()
const router = new KoaRouter()
const schema = makeExecutableSchema({
typeDefs,
resolvers
})
// Enable Cross-Origin Resource Sharing (CORS)
app.use(cors())
// Enable gzip
app.use(compress())
// Parse body
app.use(koaBody())
// GraphQL API
router.post(
apiEndpoint,
apolloUploadKoa({
uploadDir: '/tmp/uploads'
}),
graphqlKoa({
schema
})
)
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(process.env.PORT)
console.log(`Serving at http://localhost:${process.env.PORT} in ${process.env.NODE_ENV} mode.`)

View File

@ -0,0 +1,43 @@
import {NoEmitOnErrorsPlugin} from 'webpack'
import {distPath} from './config'
const config = {
devtool: 'source-map',
entry: {
index: './server.js'
},
output: {
path: distPath,
filename: '[name].js',
libraryTarget: 'commonjs2'
},
externals: /^(?!\.|\/).+/i,
target: 'node',
node: {
__dirname: true
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: process.env.NODE_ENV === 'development'
}
}
}, {
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: 'graphql-tag/loader'
}]
}
}
if (process.env.NODE_ENV === 'development') {
config.plugins = [
new NoEmitOnErrorsPlugin()
]
}
export default config

5
apollo-upload-logo.svg Normal file
View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="170" height="128" viewBox="0 0 170 128">
<title>Apollo upload logo</title>
<path fill="#00BCDE" d="M159.279 71.787c0 10.343-8.4 18.725-18.76 18.725a18.702 18.702 0 0 1-11.05-3.592 25.824 25.824 0 0 1-11.593 2.731C103.587 89.651 92 78.089 92 63.827 92 49.562 103.586 38 117.876 38a25.887 25.887 0 0 1 23.54 15.084c9.943.468 17.863 8.662 17.863 18.703zm-22.101-17.569a21.576 21.576 0 0 0-19.302-11.905c-11.91 0-21.563 9.633-21.563 21.514 0 11.878 9.654 21.511 21.563 21.511 3.827 0 7.504-.994 10.746-2.856l1.323-.76 1.157.994a14.39 14.39 0 0 0 9.416 3.483c7.98 0 14.448-6.454 14.448-14.412 0-7.957-6.468-14.411-14.448-14.411-.15 0-.307.002-.476.007l-9.741.274 6.877-3.439z"/>
<path fill="#0F2A4A" d="M112.424 74.382l-5.016-1.25 10.944-12.763 3.672 16.406-5.402-1.347c-.237.71-.473 1.41-.709 2.093-.261.759-.517 1.484-.765 2.17a78.792 78.792 0 0 1-1.437 3.728 50.767 50.767 0 0 1-10.925 16.218c-19.917 19.917-52.242 19.882-72.199-.075s-19.992-52.281-.074-72.199C49.256 8.62 78.985 7.546 99.057 24.114a5.384 5.384 0 0 1 2.094-.42 5.385 5.385 0 0 1 5.39 5.379c0 2.97-2.413 5.379-5.39 5.379a5.385 5.385 0 0 1-5.073-7.203C77.703 12.281 50.645 13.33 33.562 30.413c-18.231 18.232-18.2 47.826.075 66.1 18.274 18.274 47.868 18.306 66.1.074a46.455 46.455 0 0 0 10-14.842 74.75 74.75 0 0 0 1.355-3.518c.24-.666.489-1.371.744-2.111.195-.567.392-1.146.588-1.734zM72.092 41.448L87.23 80.651h-9.483L66.849 49.794l-6.127 16.868h9.419l2.589 7.348H58.427l-2.475 6.64H46.47l15.138-39.202h10.485z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

3
client/.env.example Normal file
View File

@ -0,0 +1,3 @@
NODE_ENV=development
PORT=3000
API_URI_URI=http://localhost:3001/graphql

1
client/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.next

View File

@ -0,0 +1,31 @@
import {Component} from 'react'
import {graphql, gql} from 'react-apollo'
class SingleUploader extends Component {
handleChange = ({target}) => {
if (target.validity.valid) {
this.props
.mutate({
variables: {
file: target.files[0]
}
})
.then(({data}) => console.log('Mutation response:', data))
}
}
render () {
return <input type='file' accept={'image/jpeg,image/png'} required onChange={this.handleChange} />
}
}
export default graphql(gql`
mutation singleUpload ($file: Upload!) {
singleUpload (file: $file) {
name
type
size
path
}
}
`)(SingleUploader)

View File

@ -0,0 +1,76 @@
import 'isomorphic-fetch'
import React from 'react'
import {
ApolloClient,
ApolloProvider,
getDataFromTree
} from 'react-apollo'
import {createNetworkInterface} from 'apollo-upload-client'
const ssrMode = !process.browser
let apolloClient = null
function initClient (headers, initialState) {
return new ApolloClient({
initialState,
ssrMode,
networkInterface: createNetworkInterface({
uri: process.env.API_URI
})
})
}
function getClient (headers, initialState = {}) {
if (ssrMode) return initClient(headers, initialState)
if (!apolloClient) apolloClient = initClient(headers, initialState)
return apolloClient
}
export default Component => (
class extends React.Component {
static async getInitialProps (ctx) {
const headers = ctx.req ? ctx.req.headers : {}
const client = getClient(headers)
const props = {
url: {
query: ctx.query,
pathname: ctx.pathname
},
...await (Component.getInitialProps ? Component.getInitialProps(ctx) : {})
}
if (ssrMode) {
const app = (
<ApolloProvider client={client}>
<Component {...props} />
</ApolloProvider>
)
await getDataFromTree(app)
}
return {
initialState: {
apollo: {
data: client.getInitialState().data
}
},
headers,
...props
}
}
constructor (props) {
super(props)
this.client = getClient(this.props.headers, this.props.initialState)
}
render () {
return (
<ApolloProvider client={this.client}>
<Component {...this.props} />
</ApolloProvider>
)
}
}
)

37
client/package.json Normal file
View File

@ -0,0 +1,37 @@
{
"name": "apollo-upload-examples-client",
"private": true,
"dependencies": {
"apollo-upload-client": "^3.0.1",
"babel-plugin-transform-inline-environment-variables": "^0.0.2",
"next": "^2.0.1",
"react": "^15.4.2",
"react-apollo": "^1.0.0",
"react-dom": "^15.4.2",
"zoo": "^0.1.9"
},
"devDependencies": {
"babel-eslint": "^7.2.1",
"standard": "^9.0.2"
},
"scripts": {
"lint": "standard",
"dev": "zoo next",
"build": "zoo next build",
"start": "zoo next start"
},
"babel": {
"presets": [
"next/babel"
],
"plugins": [
"transform-inline-environment-variables"
]
},
"standard": {
"parser": "babel-eslint",
"ignore": [
".next/**"
]
}
}

22
client/pages/index.js Normal file
View File

@ -0,0 +1,22 @@
import Head from 'next/head'
import withData from '../helpers/with-data'
import SingleUploader from '../components/single-uploader'
export default withData(props => (
<div>
<Head>
<title>Apollo upload example</title>
<style>{`
html {
font-family: sans-serif;
}
body {
margin: 2em;
}
`}</style>
</Head>
<h1>Apollo upload example</h1>
<p>Select an image to upload and view the response in the console.</p>
<SingleUploader />
</div>
))

17
client/readme.md Normal file
View File

@ -0,0 +1,17 @@
# Apollo upload examples client
An example [Next.js](https://github.com/zeit/next.js) [React Apollo client](http://dev.apollodata.com/react) using [Apollo upload client](https://github.com/jaydenseric/apollo-upload-client).
## Setup
1. Install the latest [Node.js](https://nodejs.org).
2. Run `npm install` within the `api` directory in Terminal.
3. Copy `.env.example`, rename it `.env` and customize.
For development run `npm run dev`.
For production run `npm run build && npm run start`.
## Support
- Node.js versions >= 7.6.

11
readme.md Normal file
View File

@ -0,0 +1,11 @@
# ![Apollo upload examples](https://cdn.rawgit.com/jaydenseric/apollo-upload-example/v1.0.0/apollo-upload-logo.svg)
![Github release](https://img.shields.io/github/release/jaydenseric/apollo-upload-example.svg?style=flat-square) ![Github issues](https://img.shields.io/github/issues/jaydenseric/apollo-upload-example.svg?style=flat-square) ![Github stars](https://img.shields.io/github/stars/jaydenseric/apollo-upload-example.svg?style=flat-square)
An example GraphQL API using [Apollo upload server](https://github.com/jaydenseric/apollo-upload-server) and an example [Next.js](https://github.com/zeit/next.js) [React Apollo client](http://dev.apollodata.com/react) using [Apollo upload client](https://github.com/jaydenseric/apollo-upload-client).
- [MIT license](https://en.wikipedia.org/wiki/MIT_License).
## Setup
See readmes in `/client` and `/api`.