Skip to content

Instantly share code, notes, and snippets.

@sergioramos
Last active July 22, 2020 16:35
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save sergioramos/bbf231cc1ce743b6ee9720a183f3c906 to your computer and use it in GitHub Desktop.
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