Exhale
Exhale was once Palolo.
- Run Initial Setup if you haven't already
- To run the app locally:
x go
Note: The x command lives in the /scripts directory in this repo. To run the command from anywhere, run scripts/x install.
By default, the app is accessible at http://localhost:3000. Our dev server is actually two processes. Running on port 3000 is the Vite dev server, which serves our client-side JavaScript and handles hot-module reloading. The Vite dev server proxies API requests to http://localhost:3001, which is where the actual API server lives in development.
If you only need to run the API server (but you don't need the browser client), you can just run:
pnpm run --dir packages/server dev
Using the VS Code Debugger
Server: Make sure you are running x go. In the VS Code debug panel, run "Attach to Server".
(Alternatively, quit any x go process. In the VS Code debug panel, run "Launch Server".)
Client: Make sure you are running x go. In the VS Code debug panel, run "Launch Chrome".
In both scenarios, you should be able to add breakpoints in TypeScript files via the editor.
To get the database in sync with upstream changes
We favor resetting your database on an upstream change. To reset and reseed your database, run:
x db reset
To run migrations without resetting the database:
x db migrate
Creating new migrations
If the set of migrations is out of date with the latest models.prisma file, run the same commands as above to generate a new migration. Prisma will prompt you to enter a name for the new migration and always prepends a timestamp to all migration names. Docs here.
x db migrate
Sometimes you'll create a bunch of migrations in a row as you are working on a branch. Whenever possible, flatten those migrations into a single migration before merging:
cd packages/server
rm -rm prisma/migrations/<your migrations here>
x db migrate
Managing dependencies
If the dependencies have changed upstream, run:
x update
To manage dependencies, cd into a specific package directory and use pnpm add, pnpm update, or pnpm remove.
Initial Setup
Complete Engineering Technical Onboarding before continuing.
Bash/Zsh Setup
Edit your .zshrc to include these lines
# PALOLO_ROOT should provide a path to where you have cloned the exhale project repo.
export PALOLO_ROOT=~/development/palolo
source $PALOLO_ROOT/utils/.zshrc
In addition, run scripts/x install to make the x command globally accessible.
Install our dependencies
Get Homebrew if you don't have it already.
By default, we have a script to do this for you
# Runs an `aws configure` which requires manual inputs
# So wait until you're past that before grabbing that cup of coffee
scripts/osx_dependencies.sh
# Bare metal
scripts/x install
x init
x go
# Now open localhost:3000 in your browser
# Docker
make down docker-build up
# Now open localhost:3002 in your browser
# Completely clean docker build
make down clean-db docker-build-clean up
AWS setup requires manual inputs, so keep an eye on it while it runs.
If you need to do parts of this manually:
Configure AWS CLI
brew install awscli
You will manage your AWS authenticated session using leapp. see AWS SSO with Leapp
Install Node 16
brew install node@16
brew link node@16 # It's "keg-only" by default.
Install pnpm
npm -g install pnpm
pnpm is an alternative Node.js package manager. We use it because it works better with monorepos, it helps us avoid accidental dependency imports by only exposing our direct dependencies in the top level of node_modules, and it doesn't automatically install peer dependencies.
Alternatively, install pnpm using one of the standalone methods on this page, then run pnpm env use --global 16 to install Node 16.
Install Postgres 14
brew install postgresql
If we're still on Postgres 14 and Postgres 15 gets released, this will probably change to:
# Unnecessary right now.
brew install postgresql@14
brew link postgresql@14
Install Node dependencies with pnpm
Within the root palolo.com directory, run:
pnpm install --frozen-lockfile
You can ignore the following peer dependency complaints:
- Missing
reactandreact-dom. - Missing
@babel/*from@preact/preset-viteor Next.js. - Missing
webpackfrom Next.js ornext-plugin-preact. - Missing
@prefresh/babel-pluginfromnext-plugin-preact
Install Localstack and run local AWS services
We use localstack to run a local instance of SQS when developing.
python3 -m pip install localstack
python3 -m pip install awscli-local
Currently the only AWS service that local development depends on in SQS. Create the expected queues:
cd packages/server
pnpm run queue init
Set local environment variables
x secrets
This will generate an .env containing relevant secrets and other environment variables.
If you'd like to make changes to this file, put them in local.env and re-run the secrets
command. They will be appended to the end. local.env is ignored by git.
If you'd like to manage secrets, visit the AWS Secrets Manager. Be sure to tag new secrets to an environment
or environments; see pnpm run secrets --help for more information.
Initialize local database
First, initialize the local database.
x db init
Now get up to date with the latest migrations:
x db migrate
This should run all the migrations in the prisma/migrations directory, and regenerate the
magic @prisma/client dependency.
Finally, seed the database with test data. This will create a variety of test organizations that are composed of uninvited, invited, KYC, linked but not KYC, or paycheck connected (PC) members only and some that consist of all of those types of members. For testing purposes, you can log in with the following emails using the password test:
Note: due to generating a random amount of members, for the non-exhale user options below, there is a higher likely hood a member will exist if it is a lower number. Take the ranges below with a grain of salt, it might be prone to change as time continues.
-
[first name of Exhale employee]@palolo.com
EX: giaco@palolo.com- This will log you in as an Exhale super user with unrestricted access to the test data.
-
linked[number from 1 -> ~80+]@example.com
EX: linked15@example.com- This will log you in as a linked member who has not KYCed yet.
-
kyc[number from 1 -> ~80+]@example.com
EX: kyc10@example.com- This will log you in as a KYC linked member.
-
pc[number from 1 -> ~30+]@example.com
EX: pc23@example.com- This will log you in as a pay connected member.
-
admin[number from 1 -> ~15+]@example.com
EX: admin12@example.com- This will log you in as a administrator to an organization.
- The member you log-in as may either be uninvited, signed up, or signed up AND a participant.
x db seed
Running the script above will create a significant amount of data that will take time to generate. But sometimes during local development we do not want to generate a lot of members each time. To fix this you can add the following flags after x db seed in the command line before running.
--empty: clears your database and does not fill it
NOTE: The following numbers will affect the amount of members in the Garden Cafe organization
--tiny: 13 members with random statuses--small: 53 members with random statuses--normalor justx db seed: 1003 members with random statuses
Explore local database
x db studio
This will load the Prisma studio where you can explore and edit data.
Continuous integration
We use Github Actions for CI; see .github/workflows/ci.yml for the relevant workflow.
If you are having trouble with a particular step of a workflow, try using the ssh step
to open an SSH session so you can investigate the machine that the workflow breaking on. Add the
following step immediately before the failing step:
- uses: ./.github/actions/ssh
In the actions log for the run the ssh
command you need to use will be shown. Terminate the tmux session when you are ready to continue
the workflow.
Resetting local dev environment
For a more drastic approach of simultaneously updating dependencies, updating secrets, and resetting the database of your local dev environment:
x reset
Testing
To run tests in the default test group, which is most of them (any *.spec.ts file):
pnpm run test
To run tests for a non-default group (such as for our Baas), run
PALOLO_TEST_GROUP=$group pnpm run test
# Or use the shortcuts defined in server/package.json
pnpm run test:solid
pnpm run test:noble
This will run tests in any *.spec.$group.ts file.
Testing Locally
To force a loan or KYC check to be rejected, set the user's middle name to Reject. To force them to go into review, set it to Review.
Create direct deposits for a user:
pnpm run --dir packages/server baas direct-deposit 'user-id' 'direct deposit description'
Locally preview notifications (including emails):
cd packages/notifications
pnpm run dev
Then, open http://localhost:3005. To test another renderer, add it to the renderers list at the top of packages/notifications/src/local-preview.tsx.
Using localstack to send email locally:
- Ensure Docker is running
pnpm run queue initinside ofpackages/server- Ensure the domain you are sending to is in
const allowedEmailDomains, or email will not be sent
You can reset the queue with pnpm run queue reset, but it shouldn't be necessary.
Send loan bill reminders:
Change NEXT_BILL_REMINDER_DIFFERENCES to [30], then:
pnpm run worker '{ "type": "PerkInstancesReminder", "queue": "Notifications", "data": {} }'
Docker
To push an image from local:
# Create a new builder that can do multi-architecture manifest natively
docker buildx create --use --name mybuild
# Push your image
EXPORT MY_TAG=<my deployment tag>
make DOCKER_ARGS="--platform=linux/arm64,linux/amd64 --output=type=registry" DOCKER_VERSION="${MY_TAG}" docker-build # docker-build-app/postgres/whatever
# Revert to local docker
docker buildx use default
To smoke-test changes to Dockerfile or other related scripts (e.g. docker_base_setup.sh):
# Build the image locally.
make docker-build-clean
# Bring it up.
make down && make up
# Test it out! It should be running at http://localhost:3002
Webhooks
To test webhooks (and emails) locally, first setup ngrok or an equivalent service to get a publicly-accessible
URL that routes to your local server. Once you have that running, you should configure it with
the service you want to test. In order to ensure all URLs generated by Exhale use the publicly-accessible
URL, be sure to set PUBLIC_PALOLO_DOMAIN=<ngrok-url> in your environment.
# Start ngrok
ngrok http 3000
Solid
To test Solid webhooks, use the following to create a webhook that points at ngrok:
SOLID_WEBHOOK_URL=<ngrok-url> pnpm run baas
That will create a webhook that you can find the Solid dashboard. Retrieve the Solid webhook secret key and start your dev server:
SOLID_WEBHOOK_SECRET_KEY=<key> pnpm run dev
You don't strictly need to provide the webhook secret locally, but we will need to provide it in production.