const { graphqlLambda } = require('apollo-server-lambda/dist/lambdaApollo'); | |
const gql = require('graphql-tag'); | |
const Posts = [ | |
{ | |
id: 1, | |
title: 'GraphQL fundamentals', | |
keywords: ['graphql', 'beginner', 'development'], | |
category: 'Development', | |
}, | |
{ | |
id: 2, | |
title: 'GraphQL advanced', | |
keywords: ['graphql', 'advanced', 'pro', 'development'], | |
category: 'Development', | |
}, | |
{ | |
id: 3, | |
title: 'Earthquake in Indonesia', | |
keywords: ['earthquake', 'indonesia'], | |
category: 'World', | |
}, | |
]; | |
const typeDefs = gql` | |
type Post { | |
id: ID! | |
title: String | |
keywords: [String] | |
category: String | |
} | |
type Query { | |
allPosts: [Post] | |
post(id: ID!): Post | |
} | |
`; | |
exports.handler = graphqlLambda({ | |
typeDefs, | |
resolver: { | |
Query: { | |
allPosts: (_, __, { db }) => db.posts, | |
post: (_, { id }, { db }) => | |
db.posts.find(post => post.id === Number(id)), | |
}, | |
}, | |
context: { | |
db: { | |
posts: Posts, | |
}, | |
}, | |
}); |
{ | |
"name": "sls-ncc-example", | |
"version": "1.0.0", | |
"private": true, | |
"dependencies": { | |
"apollo-server-lambda": "^2.9.6", | |
"graphql-playground-middleware-lambda": "^1.7.13", | |
"graphql-tag": "^2.10.1" | |
}, | |
"devDependencies": { | |
"@zeit/ncc": "^0.20.5", | |
"aws-sdk": "^2.546.0", | |
"prettier": "^1.18.2", | |
"serverless": "^1.54.0", | |
"serverless-plugin-ncc": "^0.4.0", | |
"serverless-pseudo-parameters": "^2.5.0" | |
} | |
} |
const lambdaPlayground = require('graphql-playground-middleware-lambda'); | |
const { ENDPOINT_URL = '' } = process.env; | |
module.exports.handler = lambdaPlayground({ | |
endpoint: ENDPOINT_URL, | |
settings: { | |
'general.betaUpdates': true, | |
'editor.cursorShape': 'line', | |
'editor.theme': 'light', | |
'editor.reuseHeaders': false, | |
'tracing.hideTracingResponse': false, | |
'editor.fontSize': 14, | |
'editor.fontFamily': | |
"SF Mono Regular, Menlo, Monaco, 'Courier New', monospace", | |
'request.credentials': '', | |
}, | |
}); |
const { name: service } = require("./package.json"); | |
const { INDIVIDUALLY = "0", NCC = "0" } = process.env; | |
const IS_INDIVIDUALLY = Boolean(JSON.parse(INDIVIDUALLY)); | |
const IS_NCC = Boolean(JSON.parse(NCC)); | |
module.exports = { | |
service, | |
plugins: [IS_NCC && "serverless-plugin-ncc"].filter(Boolean), | |
provider: { | |
name: "aws", | |
runtime: "nodejs10.x", | |
// eslint-disable-next-line no-template-curly-in-string | |
region: '${env:AWS_REGION, "eu-west-3"}', | |
// eslint-disable-next-line no-template-curly-in-string | |
stage: '${opt:stage, "development"}', | |
environment: { | |
// eslint-disable-next-line no-template-curly-in-string | |
NODE_ENV: '${env:NODE_ENV, "development"}' | |
} | |
}, | |
package: { | |
individually: IS_INDIVIDUALLY, | |
excludeDevDependencies: !IS_NCC | |
}, | |
custom: { | |
ncc: { | |
// we can ignore aws-sdk because the node runtime in lambda automatically include is | |
externals: ["aws-sdk/clients/s3"] | |
} | |
}, | |
functions: { | |
GraphQL: { | |
handler: "graphql.handler", | |
events: [ | |
{ | |
http: { | |
path: "/graphql", | |
method: "POST" | |
} | |
} | |
] | |
}, | |
Playground: { | |
handler: "playground.handler", | |
events: [ | |
{ | |
http: { | |
path: "/playground", | |
method: "GET" | |
} | |
} | |
] | |
}, | |
Upload: { | |
handler: "upload.handler", | |
events: [ | |
{ | |
http: { | |
path: "/upload", | |
method: "POST" | |
} | |
} | |
] | |
} | |
} | |
}; |
rm -rf node_modules .serverless; yarn cache clean; yarn --frozen-lockfile | |
echo "INDIVIDUALLY=false NCC=false" | |
time NODE_ENV=production ./node_modules/.bin/sls package --stage production | |
ls -lah .serverless | |
echo "INDIVIDUALLY=true NCC=false" | |
time NODE_ENV=production INDIVIDUALLY=1 ./node_modules/.bin/sls package --stage production | |
ls -lah .serverless | |
echo "INDIVIDUALLY=true NCC=true" | |
time NODE_ENV=production INDIVIDUALLY=1 NCC=1 ./node_modules/.bin/sls package --stage production | |
ls -lah .serverless |
const { format } = require('url'); | |
const S3 = require('aws-sdk/clients/s3'); | |
const Hasha = require('hasha'); | |
const { extension } = require('mime-types'); | |
const Intercept = require('apr-intercept'); | |
const { SerializeError } = require('serialize-error'); | |
const { BUCKET_NAME = 'my-bucket' } = process.env; | |
const s3 = new S3(); | |
const handleError = error => { | |
return { | |
statusCode: 500, | |
body: JSON.stringify(SerializeError(error)), | |
headers: { | |
'content-type': 'application/json', | |
}, | |
}; | |
}; | |
// accepts base64 data in the body | |
module.exports.upload = async ev => { | |
const reg = /^data:image\/([\w+]+);base64,([\s\S]+)/; | |
// separate ev.body into array of three things "intro", "mime" - which holds the type, and "data" which is the gibberish of data body | |
const [, mime, data] = (ev.body || '').match(reg) || []; | |
if (!mime || !data) { | |
return handleError(new Error('image base64 data error')); | |
} | |
// use Hasha to generate file name based on the data | |
const name = Hasha(data, { algorithm: 'md5' }); | |
// identify the extension | |
const ext = extension(`image/${mime}`); | |
const filename = `${name}.${ext}`; | |
const href = format({ | |
slashes: true, | |
protocol: 'https:', | |
host: 's3.amazonaws.com', | |
pathname: `${BUCKET_NAME}/${filename}`, | |
}); | |
const params = { | |
Body: Buffer.from(data, 'base64'), | |
Bucket: BUCKET_NAME, | |
Key: filename, | |
}; | |
// upload image | |
const [err] = await Intercept(s3.putObject(params).promise()); | |
return err ? handleError(err) : { statusCode: 201, body: href }; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment