Installation
Everything you need before you can start using wunshot effectively
Prerequisites
Section titled “Prerequisites”A Typescript App
Section titled “A Typescript App”You can set up a typescript project with any major framework.
You are not limited to frontend frameworks or frameworks at all. See how to run typescript with Node.js
Bun, Deno, and workerd also give TypeScript first-class support.
A (PostgreSQL) Database
Section titled “A (PostgreSQL) Database”You must have access to a database. If you don’t, you can start with the PostgreSQL Download Page or Detailed installation guides or see How to Use the Postgres Docker Official Image. Another good option for local development that can manage multiple versions/instances of PostgreSQL without the overhead of docker is DBngin.
There are numerous hosting/cloud options for PostgreSQL beyond the scope of this guide.
Once your database is set up, you should have connection URL that looks something like:
postgresql://USER:PASSWORD@HOST:PORT/DATABASE_NAME?PARAM_NAME=PARAM_VALUE
Read more about connection URIs
Add your connection URL to your project’s .env
file or secrets manager.
Create your folder structure
Section titled “Create your folder structure”Directoryapp/
- …
Directorydb
Directoryhelpers/
- …
Directorymigrations/ auto-generated by
drizzle-kit
- …
Directorymodels
Directoryusers
- queries.ts
- schema.ts
- validations.ts
Directoryops
- …
- index.ts
- drizzle.config.ts
Run this snippet to auto-generate the structure:
mkdir -p db/helpers db/models/users db/ops && touch db/index.ts db/models/users/queries.ts db/models/users/schema.ts db/models/users/validations.ts drizzle.config.ts
Set up TypeScript
Section titled “Set up TypeScript”Alias #
to the db
directory.
{ "compilerOptions": { "strict": true, // recommended "noUncheckedIndexedAccess": true, // recommended ... "paths": { "#/*": ["./db/*"], "@/*": ["./*"] } }}
Set up Drizzle
Section titled “Set up Drizzle”Database Connections with Drizzle ORM
Section titled “Database Connections with Drizzle ORM”Follow the installation instructions for PostgreSQL on the Drizzle ORM website for detailed directions.
-
Select your driver(s)
Select a driver based on your database provider or hosting setup. Some providers may use their own drivers, while others may rely on popular community packages like node-postgres or Postgres.js.
See Drizzle ORM - PostgreSQL for more information about supported ways to connect.
-
Install the packages with your package manager of choice
Terminal window npm i drizzle-orm # and your chosen driver(s) -
Set up your database connection
Here’s an example with the node-postgres driver. Your setup may be different.
@/db/index.ts import { drizzle } from "drizzle-orm/node-postgres";const { DB_URL } = process.env;if (!DB_URL) throw new Error("Missing db url");export const db = drizzle({connection: { connectionString: DB_URL },casing: "snake_case",// logger: true,});export const txDb = db; // node-postgres supports transactions, so this is a simple alias
Automatic Migration Generation with Drizzle Kit
Section titled “Automatic Migration Generation with Drizzle Kit”Install drizzle-kit
into your devDependencies
with your package manager of choice.
npm i -D drizzle-kit
Then configure it with drizzle.config.ts
import { defineConfig } from "drizzle-kit";
const { DB_URL } = process.env;if (!DB_URL) throw new Error("Missing db url");
export default defineConfig({ dialect: "postgresql", out: "./db/migrations", schema: "./db/models/**/*(schema|view)s.ts", dbCredentials: { url: DB_URL }, casing: "snake_case", // Print all statements verbose: true, // Always ask for confirmation strict: true,});
See the Drizzle Kit Config Reference for more information.
Add package.json
scripts for migrations
Section titled “Add package.json scripts for migrations”{ ... "scripts": { ... "db": "drizzle-kit", "db:drop": "npm run db -- drop", "db:generate": "npm run db -- generate", "db:migrate": "npm run db -- migrate", "db:push": "npm run db -- push", "db:studio": "npm run db -- studio", } ...}
Accessing env variables
Section titled “Accessing env variables”Depending on your project setup, you may need to pass environment variables to drizzle-kit explicitly.
If you try to run npm run db:generate
and trigger the Missing db url
error, then try one of the following solutions.
Use a secrets manager
Section titled “Use a secrets manager”-
Create a project on Infisical
-
Add a
DB_URL
variable to your project -
Follow the Infisical CLI installation instructions to get it set up on your machine
-
Login to Infisical on your machine
Terminal window infisical login -
Initialize Infisical in your app
from your project root infisical init -
Update the
package.json
scripts to use Infisicalpackage.json {..."scripts": {..."db": "infisical run -- drizzle-kit","db:drop": "npm run db -- drop","db:generate": "npm run db -- generate","db:migrate": "npm run db -- migrate","db:push": "npm run db -- push","db:studio": "npm run db -- studio",}...}
Read the Infisical Quickstart Guide for more detailed instructions and configuration options.
Use .env
file(s)
Section titled “Use .env file(s)”Add your DB_URL
to .env.local
:
DB_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE_NAME?PARAM_NAME=PARAM_VALUE"
npm i -D dotenv-cli
{ ... "scripts": { ... "db": "dotenv -e .env.local -- drizzle-kit", "db:drop": "npm run db -- drop", "db:generate": "npm run db -- generate", "db:migrate": "npm run db -- migrate", "db:push": "npm run db -- push", "db:studio": "npm run db -- studio", } ...}
npm i -D @dotenvx/dotenvx
{ ... "scripts": { ... "db": "dotenvx run -f .env.local -- drizzle-kit", "db:drop": "npm run db -- drop", "db:generate": "npm run db -- generate", "db:migrate": "npm run db -- migrate", "db:push": "npm run db -- push", "db:studio": "npm run db -- studio", } ...}
Install Valibot
Section titled “Install Valibot”npm i valibot
(Optional) serialize-error
Section titled “(Optional) serialize-error”Handling errors in typescript can be unintuitive. This package makes it easier to interact with errors for logging or persisting to the database.
npm i serialize-error
(Optional) server-only
Section titled “(Optional) server-only”If you are using react server components, you should use the server-only package. This can help prevent leaking secrets to the client.
npm i server-only