Initialize database. Document it. Hate life.

This commit is contained in:
Ryan Pandya 2024-10-04 23:39:04 -07:00
parent c52ac44f3c
commit 850149ebcb
14 changed files with 4368 additions and 18 deletions

View File

@ -2,19 +2,11 @@
description: Time to actually do shit.
---
# Packages and Turbo
# Repo Hygiene
So you got a project started and wasted some time writing documentation. Great!
Now, how do we get some actual functionality in this shit?
Here's what I want to get done in this chapter:
- Get typescript installed, and have its settings propagate to several different apps
- Have Baby's First Landing Page set up in the web app, inheriting the Typescript config
- Do the same for Tailwind, ESLint, Prettier???
Then, we can worry about things like "actually building software that does something" and "everything else other than running a generator and writing useless documentation".
Now, let's move on to "actually building software that does something" and "everything else other than running a generator and writing useless documentation".
## But first, wtf is @repo?
@ -33,5 +25,9 @@ Yes, everything worked fine as soon as I made the ~31 edits, ran `pnpm install`,
## Another side-quest: Git Repository
There's really no reason to document this. I already have a git repo initialized; I created one on `git.ryanpandya.com` and synced all this crap with it.
There's really no reason to document this. I already had a local a git repo initialized (can't remember if this happens by default in my `init-nix` script, or if I ran `git init`, you're on your own); I created a cloud copy on `git.ryanpandya.com` and synced all this crap with it.
:::note
Make sure you de-select "Initialize repository" so that the first commit from VSCode actually goes through instead of causing a mountain of sync conflicts and merge headaches.
:::

View File

@ -0,0 +1,56 @@
---
description: The scary stuff.
---
# Database
The scary part.
This is where my casual fucking around is about to slam face-first into a brick wall.
It's time to:
- Create a database package.
- ~Connect to a postgres database.~ JK, Fuck postgres, I'll use SQLite to keep things easy for now.
I'll worry about formalizing these things later (like, how can I configure these through environment variables, make things multi-user... etc. Not my problem right now. This is single-user and mostly for learning).
## Setting Up Drizzle
Continuing my copy-catting from Hoarder, it looks like Drizzle is the thing to use for database schema type shit in Javascript/Typescript/Node land.
Let's see how that works.
### Create folder
`mkdir packages/db`.
`pnpm init`.
Shamelessly copy code from Hoarder.
### Set up SQLite with Drizzle
```
pnpm add -D drizzle-kit
```
Create `drizzle.config.ts`.
Honestly. just copy the code from the following files:
- drizzle.config.ts
- drizzle.ts
- index.ts
- migrate.ts
- package.json
- schema.ts (PLACEHOLDER SHIT FROM TUTORIAL)
Then, *from the db directory*, run `pnpm drizzle-kit generate` and it'll make the fucking database file, after which, from the workspace project root, `pnpm db:migrate` will do the goddamn migration, after which, `pnpm db:studio` will load Drizzle Studio at some arcane Avahi `local.drizzle.studio` URL and you'll see the fucking table it made.
I hate Javascript development.
But, it's starting to work, goddamn it.
### Load all this crap from the web app
TODO tomorrow.

View File

@ -5,7 +5,9 @@
"build": "turbo build",
"dev": "turbo dev",
"lint": "turbo lint",
"format": "prettier --write \"**/*.{ts,tsx,md}\""
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
"db:studio": "pnpm --filter @lifetracker/db studio",
"db:migrate": "pnpm --filter @lifetracker/db run migrate"
},
"devDependencies": {
"prettier": "^3.2.5",

View File

@ -0,0 +1,14 @@
import "dotenv/config";
import type { Config } from "drizzle-kit";
const databaseURL = "./lifetracker.db";
export default {
dialect: "sqlite",
schema: "./schema.ts",
out: "./drizzle",
dbCredentials: {
url: databaseURL,
},
verbose: true,
} satisfies Config;

20
packages/db/drizzle.ts Normal file
View File

@ -0,0 +1,20 @@
import "dotenv/config";
import { drizzle } from "drizzle-orm/better-sqlite3";
import Database from "better-sqlite3";
import * as schema from "./schema";
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
import path from "path";
import dbConfig from "./drizzle.config";
const sqlite = new Database(dbConfig.dbCredentials.url);
export const db = drizzle(sqlite, { schema });
export function getInMemoryDB(runMigrations: boolean) {
const mem = new Database(":memory:");
const db = drizzle(mem, { schema, logger: true });
if (runMigrations) {
migrate(db, { migrationsFolder: path.resolve(__dirname, "./drizzle") });
}
return db;
}

View File

@ -0,0 +1,4 @@
CREATE TABLE `events` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`description` text NOT NULL
);

View File

@ -0,0 +1,40 @@
{
"version": "6",
"dialect": "sqlite",
"id": "74097c41-1958-4fc8-8371-6e31b3071eb9",
"prevId": "00000000-0000-0000-0000-000000000000",
"tables": {
"events": {
"name": "events",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@ -0,0 +1,13 @@
{
"version": "7",
"dialect": "sqlite",
"entries": [
{
"idx": 0,
"version": "6",
"when": 1728109876982,
"tag": "0000_worried_may_parker",
"breakpoints": true
}
]
}

17
packages/db/index.ts Normal file
View File

@ -0,0 +1,17 @@
import Database from "better-sqlite3";
import { ExtractTablesWithRelations } from "drizzle-orm";
import { SQLiteTransaction } from "drizzle-orm/sqlite-core";
import * as schema from "./schema";
export { db } from "./drizzle";
export * as schema from "./schema";
export { SqliteError } from "better-sqlite3";
// This is exported here to avoid leaking better-sqlite types outside of this package.
export type LifetrackerDBTransaction = SQLiteTransaction<
"sync",
Database.RunResult,
typeof schema,
ExtractTablesWithRelations<typeof schema>
>;

BIN
packages/db/lifetracker.db Normal file

Binary file not shown.

4
packages/db/migrate.ts Normal file
View File

@ -0,0 +1,4 @@
import { db } from "./drizzle";
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
migrate(db, { migrationsFolder: "./drizzle" });

32
packages/db/package.json Normal file
View File

@ -0,0 +1,32 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@lifetracker/db",
"version": "0.0.1",
"private": true,
"main": "index.ts",
"scripts": {
"typecheck": "tsc --noEmit",
"migrate": "tsx migrate.ts",
"studio": "drizzle-kit studio"
},
"dependencies": {
"better-sqlite3": "^9.4.3",
"dotenv": "^16.4.1",
"drizzle-orm": "^0.33.0",
"expo-sqlite": "^14.0.6",
"tsx": "^4.7.1"
},
"devDependencies": {
"@lifetracker/eslint-config": "workspace:*",
"@lifetracker/typescript-config": "workspace:*",
"@tsconfig/node21": "^21.0.1",
"@types/better-sqlite3": "^7.6.9",
"drizzle-kit": "^0.24.2"
},
"eslintConfig": {
"root": true,
"extends": [
"@lifetracker/eslint-config/base"
]
}
}

10
packages/db/schema.ts Normal file
View File

@ -0,0 +1,10 @@
import {
sqliteTable,
integer,
text,
} from "drizzle-orm/sqlite-core";
export const events = sqliteTable("events", {
id: integer("id").primaryKey({ autoIncrement: true }),
description: text("description").notNull(),
});

4154
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff