Bevor relies on several different components:
- NextJS application
- PostgreSQL + Prisma Client
- Vercel Blob Storage
- Smart Contracts + Blockchain Data
1-3 are managed through this repository. 4 is managed through the bevor-v1 repository.
-
Install packages
yarn install -
Copy the example env variables to a local env
cp .env.example .env.local -
Configure the local env file In
DATABASE_URLyou'll likely need to update<username>to be your device's username, runwhoamito grab this. The<db_name>can be whatever you'd like for local development, I usedbevor. We'll by default run it on localhost:5432.
-
Make sure
psqlis installed: Runpsql --version. If it is installed, skip to (3) -
Install postgresql Run
brew install postgresql@15. The install will show you some instructions for adding psql to PATH. Make sure to follow that. -
Make sure postgresql is running locally Run
brew services info --all. If you see thatpostgresqlis running and loaded, you can skip all remaining steps. Also, runningbrew services listwill show which services homebrew manages and their corresponding statuses. -
Start the postgres server Run
brew services start postgresql. It will default run on localhost:5432. You can stop the service by runningbrew services stop postgresql
(Feel free to ignore this portion)
Once the postgres service is running, you can use psql to observe the DB locally. Running psql -l will show your databases.
There are 2 ways to connect to the DB instance, if needed. <username> and <dbname> correspond to the values set in your .env.local file. If you had never started the server (and never created the DB instance for this project), these likely will not work:
psql -U <username> -d <dbname>
psql "postgresql://<username>@localhost:5432/<dbname>"
You can also use the prisma studio yarn db:studio to connect to a GUI on localhost:5555 to interact with the data.
In practice, we use Neon to manage our postgres database, but locally, we'll rely on the homebrew postgres instance.
A note on prisma ORM strategy Support for migration reversions is not great. I wanted to keep the pattern of separating out the migration creation, and the running of the migration. I also create a script to generate down migrations automatically, which is quite useful compared to needing to manually revert the schema file, run a migration, then delete the files (in development, at least).
To set up the prisma client, make sure the environment variables are set. For local testing, we can rely on a local connection that was setup above.
Generate the Prisma Client
Run yarn run db:generate, which will re-run the existing migration history and generate the prisma client. If it is your first pass at setting up the repository, you'll need to run this.
By default, the Prisma Client is generated into ./node_modules/.prisma/client
Seeding the DB As we're integrating both off-chain (postgres) and on-chain (blockchain) data, seeding is a bit more confusing than normal. Should only be used in local development.
- Open the
bevor-v1repository in the terminal - Start the local blockchain via hardhat
- Open a new terminal, deploy the smart contracts in
bevor-v1to the local blockchain via hardhat - Navigate back to this repository.
If it is your first time interacting with the repository, simply run yarn db:seed. Otherwise, follow below.
There are a few options that can be taken after this. Seeding is partitioned into 2 scripts: prisma/seed-onchain.ts and prisma/seed-offchain.ts. This is useful for preventing having to regenerate off-chain (postgres) data every time the local blockchain is reset.
Running prisma/seed-onchain.ts when the local blockchain is not empty will result in failure.
Running prisma/seed-offchain.ts when the local postgres instance is not empty will result in failure.
Option 1:
Run yarn db:reset. This will clear all existing data in the local postgres DB, then run the prisma/seed.sh script. This will seed off-chain data, then on-chain, sequentially.
Option 2:
Run yarn db:seed. This will do the same as above, without clearing initial data. This will fail if the data already exists, as we have unique constraints on certain fields. You can run yarn db:clear to wipe the DB, then yarn db:seed. Running these 2 has the same effect as Option 1. This option is only useful if the DB is initially empty.
Option 3:
If your off-chain data is already seeded, but the local blockchain had been reset, you can standalone run the on-chain seeding using yarn db:seed:onchain. This will execute on-chain transactions and populate the postgres instance with appropriate on-chain references.
Option 4:
Manually seed both off-chain and on-chain data, sequentially. Run yarn db:seed:offchain (this will fail if the postgres DB is already populated). Then run yarn db:seed:onchain (this will fail if the local blockchain had already run this seeding script's onchain txns). Running in the wrong order can lead to failures, as the postgres observations won't exist yet for the on-chain data to populate.
Note: whenever changes are made to the prisma schema, you need to run yarn run db:generate to update the Prisma Client.
Managing Changes
If changes are made to the Prisma schema during local development, you can run yarn run db:push to quickly iterate on syncing the prisma schema with the DB schema, without creating migrations.
Once a desired "end state" is reached in development, you can actually create the necessary migrations by running yarn run db:migrate
If you want to undo yarn run db:push experiments, you can run yarn run db:reset, which will also run the seed script. yarn run db:clear does the same, without seeding.
When deploying Prisma to Vercel, Vercel automatically caches dependencies on deployment. This might result in an outdated version of the Prisma Client when the Prisma schema updates. To be safe, we use the vercel-build script to the package.json file, where we generate the prisma client, deploy our migrations (if any new ones exist), THEN build the nextJS app.