Version 1.0.0.
Initial release.
This commit is contained in:
commit
aa63c4c500
11
.editorconfig
Normal file
11
.editorconfig
Normal 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
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
*.log
|
||||
yarn.lock
|
||||
.env
|
||||
.DS_Store
|
||||
2
api/.env.example
Normal file
2
api/.env.example
Normal file
@ -0,0 +1,2 @@
|
||||
NODE_ENV=development
|
||||
PORT=3001
|
||||
1
api/.gitignore
vendored
Normal file
1
api/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/dist
|
||||
4
api/config.js
Normal file
4
api/config.js
Normal 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
58
api/package.json
Normal 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
17
api/readme.md
Normal 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
13
api/resolvers.js
Normal 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
22
api/schema.graphql
Normal 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
49
api/scripts/dev.js
Normal 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
45
api/server.js
Normal 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.`)
|
||||
43
api/webpack.config.babel.js
Normal file
43
api/webpack.config.babel.js
Normal 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
5
apollo-upload-logo.svg
Normal 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
3
client/.env.example
Normal file
@ -0,0 +1,3 @@
|
||||
NODE_ENV=development
|
||||
PORT=3000
|
||||
API_URI_URI=http://localhost:3001/graphql
|
||||
1
client/.gitignore
vendored
Normal file
1
client/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.next
|
||||
31
client/components/single-uploader.js
Normal file
31
client/components/single-uploader.js
Normal 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)
|
||||
76
client/helpers/with-data.js
Normal file
76
client/helpers/with-data.js
Normal 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
37
client/package.json
Normal 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
22
client/pages/index.js
Normal 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
17
client/readme.md
Normal 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
11
readme.md
Normal file
@ -0,0 +1,11 @@
|
||||
# 
|
||||
|
||||
  
|
||||
|
||||
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`.
|
||||
Loading…
x
Reference in New Issue
Block a user