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