serverless / serverless-graphql

Serverless GraphQL Examples for AWS AppSync and Apollo
https://www.serverless.com
MIT License
2.72k stars 364 forks source link

V0 Goals #1

Closed austencollins closed 8 years ago

austencollins commented 8 years ago

The goal here is not just to create the ultimate boilerplate project for building serverless applications, but to create an application boilerplate with the lowest total cost of ownership (e.g., code, administration, cost) by leveraging new tech (e.g., Lambda, GraphQL). Here is what the initial implementation should include:

kevinold commented 8 years ago

@ac360 Absolutely! I'll get a basic GraphQL setup going in the next few days on a separate branch. I'll keep you posted.

austencollins commented 8 years ago

Thanks @kevinold! We're wrapping up V0.5 and then we're going to jump on this!

ryansb commented 8 years ago

Would you want to have a python component in there too?

austencollins commented 8 years ago

@ryansb What do you think is the right approach here:

austencollins commented 8 years ago

Also, I appreciate everyone's help here. Please let me know via email if you would like to be listed as the team behind this project in the README. This is a project we will be putting lots of resources behind.

ryansb commented 8 years ago

I think it'd be fine to just include one or two Python components in the app, maybe performing a different function (I've got some Python GraphQL work started, actually) because most of the concepts are identical between languages so a whole app seems redundant to me.

Also when we say "boilerplate" are we imagining people will clone it and use it as a base for their application, or do we intend for it to just be an example for devs to reference when building their own?

pmuens commented 8 years ago

Awesome! What do you guys think about a React & Redux based client side implementation?

I've done a minimalistic Twitter clone with React, JSON Web Token (JWT) and Reflux (I'll blog about that soon). Maybe I can work on something related here...

austencollins commented 8 years ago

@pmuens That would be fantastic. I think we just need a landing/sign-up/sign-in page and a user dashboard. Something very simple is preferred :)

pmuens commented 8 years ago

Great! Then I'll work on this one!

austencollins commented 8 years ago

@ryansb This is going to be a base for people's applications, not an example. I believe we should not mix languages in this. There will be some redundancy, but I think we should make a Python version of this.

austencollins commented 8 years ago

Ok, I have improved the scaffolding slightly to work with Serverless V0.5 which has no concept of components. It doesn't run yet. But this is how it will look.

@pmuens @kevinold How can we help your efforts here (aside from get v0.5 released already)?

kevinold commented 8 years ago

@ac360. This structure is awesome! I'm getting the basic GraphQL pieces together and will push up some ideas in the next day or two. I'm not focused on data storage or retrieval but just the GraphQL structures at the moment once those are in place we can implement the others quickly.

I'll be certain to mention any issues I'm running into.

On Mar 8, 2016, at 5:50 PM, Austen notifications@github.com wrote:

Ok, I have improved the scaffolding slightly to work with Serverless V0.5 which has no concept of components. It doesn't run yet. But this is how it will look.

@pmuens @kevinold How can we help your efforts here?

— Reply to this email directly or view it on GitHub.

austencollins commented 8 years ago

@kevinold Thanks. We're going to work on the auth function first. It will use API G's new authorizers feature.

kevinold commented 8 years ago

@ac360 I've pushed a basic GraphQL UserType and implemented two separate Schema's - Admin and Public - that are each accessible via their respective functions. For now, I've centralized all data retrieval into dynamo.js for example purposes, and we can separate and adjust as we see fit.

This should be enough of the basics, minus the Optimizer plugin and validation that it runs.

Let me know of any specific adjustments, additions, etc.

erikerikson commented 8 years ago

@ac360 re: language mixing. Given the changes today, it would be simple and beneficial to show mixed python and node.js in the same project. Without some example substance, I think this effort could provide less value than is possible.

More generally... Nothing would block a dead simple hello world example from also being offered. I believe that broadly speaking, it is easy for us to cut away clearly delineated boilerplate but harder to create the right boilerplate for standard circumstances. Maybe this is asking for endless battles about people's favorite components being featured. In that case, strike my feedback; that would suck. But, if we could slide the absolute basics in... an absolutely basic example of each supported event type, an array of api gateway lambda integration options, a dynamo db integration and example CFT (used by one of the basic lambda examples), et cetera, I think it would go a long way to helping people get started. The more that you cheaply reduce redundancy among the userbase (without obviating engagement with the platform) the more you create success around your effort so as to give it an increasing life of its own.

That said, it can be easy to get distracted by bells and whistles. The core is always the priority.

austencollins commented 8 years ago

@kevinold WOW. Great job. Incredible.

ATM, I'm favoring JSON Web Tokens for authorization. We might just save these in DynamoDB for now. not sure if these should be included in the GraphQL implementation. More details coming shortly...

austencollins commented 8 years ago

@erikerikson Great points. But I'd rather keep things simple and focused at the moment. Let's focus on node.js and build out a great boilerplate.

pmuens commented 8 years ago

Great guys! I'll use the API @kevinold built. However I'm not that familiar with the new API Gateway custom authorizers. In my recent project I've just send the token via a custom header to the lambda function which uses the Node.js JWT package to validate it.

Perhaps someone can chime in on this.

Do you think we should use Redux or Flux? Not sure which is more prominent but Redux is a slightly improvement compared to Flux.

kevinold commented 8 years ago

@pmuens Definitely Redux. I have a complete boilerplate here (https://github.com/kevinold/hapi_webpack_redux_boilerplate) with hapi.js but the Redux pieces can be abstracted easily. Let me know if I can help get this scaffolding in place.

pmuens commented 8 years ago

@kevinold Thank you! Great. I was looking for something like that!

pmuens commented 8 years ago

Just started the work on this one today. Got a basic setup up and running. Next step is to wire things up with GraphQL via Lambda.

austencollins commented 8 years ago

Nice @pmuens! We're just about to release V0.5. It includes new Runtime classes. We just need to make a babel Runtime then we can get this running. @kevinold

kevinold commented 8 years ago

@ac360 I need to know where to hook in the optimizer plugin and I can get those files in place in the next day or two.

Kevin Old kevin@kevinold.com

On Thu, Mar 10, 2016 at 11:39 AM, Austen notifications@github.com wrote:

Nice @pmuens https://github.com/pmuens! We're just about to release V0.5. It includes new Runtime classes. We just need to make a babel Runtime then we can get this running. @kevinold https://github.com/kevinold

— Reply to this email directly or view it on GitHub https://github.com/serverless/serverless-app/issues/1#issuecomment-194971439 .

austencollins commented 8 years ago

@kevinold Maybe you could suggest the best route here:

• We just added Runtime classes in V0.5 • Every runtime will have its own Runtime class • The Runtime classes have scaffold, build and run methods. This will be called in the respective actions. • Plugin developers can add their own custom Runtimes via a new addRuntime() method • We're going to add a Babel runtime to the core

How should we best add a Babel runtime to Serverless Framework core? What node_modules should we leverage to do this. Should we keep using Browserify? You can view an example of the Python Runtime class here, but it doesn't have a build method since that is unnecessary: https://github.com/serverless/serverless/blob/v0.5/lib/RuntimePython27.js

pmuens commented 8 years ago

Great. Really like the new release!

Unfortunately I face an issue. When I run npm install in the project root to install the client-s3 npm package and run serverless after that I get this error:

/serverless/node_modules/bluebird/js/release/async.js:49
        fn = function () { throw arg; };
                           ^

Error: Cannot find module '/serverless/lib/ServerlessError'
    at Function.Module._resolveFilename (module.js:326:15)
    at Function.Module._load (module.js:277:25)
    at Module.require (module.js:354:17)
    at require (internal/module.js:12:17)
    at module.exports.ServerlessPlugin._prompt (/serverless-app/node_modules/serverless-client-s3/index.js:5:20)
    at Serverless._loadPlugins (/serverless/lib/Serverless.js:284:25)
    at Serverless.loadProjectPlugins (/serverless/lib/Serverless.js:253:12)
    at /serverless/lib/Serverless.js:110:15
From previous event:
    at Serverless.init (/serverless/lib/Serverless.js:105:8)
    at Object.<anonymous> (/serverless/bin/serverless:17:12)
    at Module._compile (module.js:398:26)
    at Object.Module._extensions..js (module.js:405:10)
    at Module.load (module.js:344:32)
    at Function.Module._load (module.js:301:12)
    at Function.Module.runMain (module.js:430:10)
    at startup (node.js:141:18)
    at node.js:980:3

However it works if I don't install the client-s3.

austencollins commented 8 years ago

@pmuens We haven't updated the Client-S3 plugin to work with V0.5 yet. This boilerplate can't be run yet as a result. We're just a day away from finishing everything and getting this running :)

pmuens commented 8 years ago

Alright. Great. I don't need it right now so no need to hurry. :smile:

pmuens commented 8 years ago

@ac360 I would like to run this on AWS for testing purpose. I get this error: Function name "auth" is already taken in the project. Function names must be unique across a project as of Serverless v0.5

Is it because 0.5 lacks components?

Any chances for a fix so that one can run the project?

kevinold commented 8 years ago

@ac360 Definitely stay with Babelify. I need to understand the runtimes a bit more before I can comment on them, but I assume the node runtime would look for a .babelrc file or config in another json file?

Kevin Old kevin@kevinold.com

On Thu, Mar 10, 2016 at 1:13 PM, Philipp Muens notifications@github.com wrote:

@ac360 https://github.com/ac360 I would like to run this on AWS for testing purpose. I get this error: Function name "auth" is already taken in the project. Function names must be unique across a project as of Serverless v0.5

You said that it's not yet ready for 0.5 usage (because of lack of components in 0.5).

Any chances for a fix so that one can run the project?

— Reply to this email directly or view it on GitHub https://github.com/serverless/serverless-boilerplate/issues/1#issuecomment-195005591 .

kevinold commented 8 years ago

@ac360 I see 2 ways Babel could be called via Runtime's build either:

Just some initial thoughts after reading your message again.

pmuens commented 8 years ago

I've just submitted a PR which implements a React / Redux client. I've implemented the index and show actions to show all users and one specific user. Will add other actions such as delete or update / create the upcoming days.

I've done the following to get this up and running on AWS (I've not submitted PRs for those, because ) I'm not quite sure if it's done properly / updates for the used plugins are available):

Updated the dependencies of the package.json file for the project as follows:

"aws-sdk": "^2.2.43",
    "babel-preset-es2015": "^6.6.0",
    "babelify": "^7.2.0",
    "bluebird": "^3.3.4",
    "graphql": "^0.4.18",
    "graphql-custom-types": "^0.2.0",
    "serverless-client-s3": "0.0.1",
    "serverless-optimizer-plugin": "git+ssh://git@github.com/serverless/serverless-optimizer-plugin.git"

Added the serverless-optimizer-plugin to the plugins array

Added babelify rules transformations in the public s-function.json file:

"optimize": {
      "exclude": [ "aws-sdk" ],
      "transforms": [
        {
          "name": "babelify",
          "opts": {
            "presets": [
              "es2015"
            ]
          }
        }
      ]
    }

To run it you need to do the following:

  1. Add some users to your DynamoDB users table.
  2. replace the API_URL (in actions/index.js) with your API Gateway URL
  3. cd client/src/
  4. npm start
  5. go to http://localhost:8080

Let me know what you think of this implementation.

kevinold commented 8 years ago

@pmuens SO AWESOME! I will give this a trial run tonight but have reviewed the commits and all looks good so have merged the PRs! I'll report back!

pmuens commented 8 years ago

@kevinold Thank you very much.

Don't forget to replace the API_URL (in actions/index.js) with your API Gateway URL (forgot to mention that in the comment above).

To run the client you need to type: cd client/src/ npm start

and go to http://localhost:8080

austencollins commented 8 years ago

@pmuens AWESOME. Will review this later today. The hold up is still V0.5. Almost done!

pmuens commented 8 years ago

@ac360 thank you! I've just finished the CRUD implementation and added some simple styling so that it looks neat.

Furthermore I've submitted another PR (https://github.com/serverless/serverless-boilerplate/pull/6) so that you can see how my lambda functions are configured.

If you apply those two PRs you should be up and running to tinker around with the CRUD functionality.

kevinold commented 8 years ago

@pmuens Awesome! I did not get a chance to test yesterday's commits, but it is on my list for today as well as this new PR #6!

kevinold commented 8 years ago

@pmuens I've merged both PR's and as mentioned in #5 I think there might be a way to manage the overall state passed down to the new and edit components in a parent component, but there might not be. I have worked very little with React Router and the way you have implemented might be the best way, so don't take this as discouragement, more of my confusion with managing state and using the router out of my normal usage.

pmuens commented 8 years ago

@kevinold Thank you. Yes, refactor it as needed! I'm curious to see best practices. There are so many different ways to do this so it's a great way to learn something new :-D

pmuens commented 8 years ago

I have a question about authentication. I'm currently developing a new Serverless application where I use this boilerplate to tinker around. I've implemented JWT based authentication into it.

Right now I'm passing the token as a parameter through GraphQL (this is a quick hack and will be changed later on).

When I've done some investigation about GraphQL and authentication I stumbled upon this blog post: https://medium.com/@clayallsopp/graphql-and-authentication-b73aed34bbeb#.5ft8idd6b

I find the "viewer" approach (also used by Facebook) which uses the JWT as a parameter and is described at the end of the post very appealing.

Should we implement something like this in this boilerplate?

There are also custom authorizers which are planned to be implemented in the auth functions. But it's bound to an endpoint.

Our boilerplate uses two endpoints (one for public and on for admin) so adding the custom authorizer to this endpoints would lock out users who wants to create an account / sign in through those endpoints. Maybe the viewer query approach (taken from the blog post above) would be better here.

I hope that this comment is understandable :laughing:. Been staring at WebStorm for too long :smile_cat:

austencollins commented 8 years ago

@pmuens Whoops, I just added some custom authorizer related stuff before reading your post and the link you provided. It looks like Facebook is using the viewer pattern. If that's the case, then it is definitely of interest. I'll read the article you linked tomorrow, then write a follow up post here.

Fortunately, custom authorizer support in V0.5 is working well.

Unfortunately, we temporarily broke the optimizer plugin in the most recent version of V0.5. @minibikini is working on that. He's also working on this https://github.com/serverless/serverless-runtime-babel which should offer a much better UX for using Babel with Serverless.

pmuens commented 8 years ago

@ac360 Great progress so far! :+1:

Yes, the custom authorizers functionality is great. But if we use one endpoint (like we do with GraphQL) where everything is fiddled through we could not use the authorizers functionality because authentication ("run the signIn function") is also done with this one endpoint which needs an authentication beforehand (as far as I understood it. Don't know if it's correct.).

pmuens commented 8 years ago

FYI: Here's another post about authentication with GraphQL. However I like the viewer pattern more.

http://rmosolgo.github.io/blog/2015/08/04/authorization-in-graphql/

kevinold commented 8 years ago

@pmuens @ac360 I wasn't able to review earlier this week but I'll be testing and reviewing the changes from this past week this weekend. I'll report any issues.

kevinold commented 8 years ago

@ac360 I'm finally getting a chance to test this out and using v0.5 tonight I ran into https://github.com/serverless/serverless/issues/855 when I needed to create my _meta folder for this project via sls project init.

@pmuens sorry for the delay but hoping to get you feedback in the next day or two.

austencollins commented 8 years ago

@kevinold Yes, we are working on this one right now! Updates coming shortly...

kevinold commented 8 years ago

@ac360 no worries, just wanted to report :D

pmuens commented 8 years ago

@kevinold No problem. I'm still running at 78ee8a101eaa48b12eda49da9d85901f6b303c0a as it's one of the last stable versions which works for me.

@ac360 Great progress so far! Really excited about v0.5!

pmuens commented 8 years ago

Hey everyone, After running on v0.5 I get the following error:

{
  "errorMessage": "Use of const in strict mode.",
  "errorType": "SyntaxError",
  "stackTrace": [
    "Module._compile (module.js:439:25)",
    "Object.Module._extensions..js (module.js:474:10)",
    "Module.load (module.js:356:32)",
    "Function.Module._load (module.js:312:12)",
    "Module.require (module.js:364:17)",
    "require (module.js:380:17)"
  ]
}

Here's the screenshot of the logs.

bildschirmfoto 2016-03-23 um 11 06 46

It has something todo with the babel runtime plugin: https://github.com/serverless/serverless-runtime-babel/blob/master/lib/RuntimeBabel.js#L233

Just opened an issue in the Babel runtime repo: https://github.com/serverless/serverless-runtime-babel/issues/2

eahefnawy commented 8 years ago

Guys, I'm starting to implement JSON Web Token to our custom authorizer. It obviously needs a secret key to decode/encode the token. Do you guys think it's best to have this secret in an env var or cert.pem? Most examples online use cert.pem which is probably much stronger, but I'm worried about having the cert file in the file system.

What you guys think?

pmuens commented 8 years ago

I've implemented it with environment variables recently which works like a charm and can be configured easily.