This repository has been archived by the owner on Dec 20, 2024. It is now read-only.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fullstack interview assignment submission
Hello Contra team!
I'm submitting my solution for the interview assignment. I chose the backend option, but also did a small part of the frontend part, as an extra.
Checkout my Loom
How to run the code
First, copy and rename the
.env.sample
file to.env
, it will store the environment variablesthen, spin up the postgres container
it will run and detach the container.
Now you can run the database migrations
and seed the database
With that, you can run the dev server
The api can be found in
localhost:5000/graphql
and the UI can be found inlocalhost:3000
Overall changes
In an effort to get closer to the stack described in the job description, I opted to make this into a monorepo using TurboRepo, and used graphql-helix for graphql on the server.
Root module
.env.sample
file.package.json
to run turbo actionsturbo.json
file to setup turbo monorepo optionsBackend
Database Schema
This is the database schema diagram.
value
in theuser_feature_flag
table is optional and allows to override the original flag value for each user, meaning that if it is not filled, the user will receive the flags original value.Seed
Added a script to seed the database with flags and users located in
backend/src/bin/seed
faker
to generate fake dataINSERT
query.Graphql schema
The graphql schema follows the same structure as the database schema, except for the relationship table.
User
type includes aflags: [Flag!]!
collection to allow fetching the user's feature flags. (inner join)Flag
resolver within the user type will fetch only the flags assigned to the user.I used the
typescript-graphql-request
andtypescript-operations
plugins to generate an sdk for the schema, writing the operations in a separate file. That makes it very easy to generate a graphql client client to query the api on integration tests.Config
I implement a function to validate environment variables and export the database connection. It uses the
envalid
library for that insrc/config/databaseConfiguration.ts
.Tests
I implemented integration tests for each api endpoint. These tests are used to test the endpoints automatically without having to open postman or the graphiql tool.
The test files are in the same folder as the resolver files, and all of them follow the setup, execute and assert, making it very easy to read and understand. All tests also build and teardown any needed test objects, so there isn't dirty data left in the database after the tests.
Resolvers
The resolvers are very simple, they receive the query parameters, call the database layer, and parse the results back to the response.
Usually I also make sure to log the request context and parameters on each call using structure logs, but because of the limited time, I dind't do it for the assignment.
Frontend
As an extra, I decided to implement the modal stacking and closing feature on the frontend assignment. This feature works by having a global modal context managing a shared modal state.
document.body
by theModalContextWrapper
.