Imagine that you have to come up with a complex backend and frontend in a short time.
I was in this situation a few times and decided to create a sample application that seems to be a good solution for this problem.
Link below:
https://github.com/stokilo/pg-publicThe central piece of the puzzle is Postgraphile library
https://www.graphile.org/It allows you to generate GraphQL schema from the relational database. Provided link points to the extensive documentation.
I will not repeat what is described there. Only a few words about how it works. Postgraphile author suggests creating Postgres schema for public access. All tables/views/functions in such schema will be processed by the library and converted into GraphQL schema/server. Other private tables are separated in non public schemas. My application generated this schema during migration and cached it in S3. All lambdas that serve API requests are initializing GraphQL server from the S3 cache file. Thanks to that, startup time is low.
Postgraphile has its own example application on github for AWS Lambda deployment. My version is focused more on integration with React/SST and Typescript generation. I spend some time generating correct types for URQL library and adding database migrations.
Database migration and schema generation are performed in a single step. Every time I add a new table, all Typescript queries/models are regenerated. React client queries too. This allows me to quickly iterate and focus on client side changes only.
I've implemented two simple fronted pages. The first page is a TODO to test 1-N relation from GraphQL schema generated as described before. I wanted to check how good Typescript code outputs from the codegen tool. My GraphQL codegen config :
It generates files from the gql React code gql definitions. It also converts Postgraphile schema to api.d.ts file that I can use to case my URQL queries. Thanks to that autocomplete works for every field that I add to my queries.
The second page is simple GraphQL query viewer. I added it for testing. It allows you to enter query and get a JSON result from the server. My use-case for this page was simple. I add a new table or relation, run migration, and I can query GraphQL lambda endpoint using my client. Or I can write React code with working autocomplete in the .ts files.
I generate only queries from database tables. I don't generate mutations because it was hard for me to do the server validation and security checks. However, it is possible to do that if it is needed. For read queries in TODO example I followed RLS (Row Level Security) tutorial from Postgraphile. Setup below:
Each table can have a policy defined as what a given user can see from the public GraphQL schema. When you define your schema to include USER_ID column, it allows you to restrict access per user. User id for executed queries is injected in Lambda layer. It could be extracted from JWT, I didn't have time to finish this part. Postgraphile allows processing JWT on the database level. It was too 'low' for me. However RLS works fine and for a simple application I think it makes a lot of sense.
Please check the code in github and run it with SST. You can change the db tables and query new data in client code right after migration. Easy and you can finally focus on nice UI features :)