Remove events schema; Create days schema; Add some dev tooling; Document above
This commit is contained in:
parent
850149ebcb
commit
9602e55f04
@ -49,8 +49,4 @@ Then, *from the db directory*, run `pnpm drizzle-kit generate` and it'll make th
|
|||||||
|
|
||||||
I hate Javascript development.
|
I hate Javascript development.
|
||||||
|
|
||||||
But, it's starting to work, goddamn it.
|
But, it's starting to work, goddamn it.
|
||||||
|
|
||||||
### Load all this crap from the web app
|
|
||||||
|
|
||||||
TODO tomorrow.
|
|
||||||
83
apps/docs/docs/how-i-built-this/04-babys-first-schema.md
Normal file
83
apps/docs/docs/how-i-built-this/04-babys-first-schema.md
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
---
|
||||||
|
description: Time for some actual functionality, believe it or not.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Baby's First Schema
|
||||||
|
|
||||||
|
Unsurprisingly, this takes place in the database part of the project, which is `packages/db`.
|
||||||
|
|
||||||
|
The idea will be to define a new file, `day.ts`, in `packages/db/schema/`, and put the columns and constraints in there.
|
||||||
|
|
||||||
|
If I'm understanding correctly, a difference vs. Phoenix or Rails is that you don't have to write the migrations yourself: just edit the schema file and you can `drizzle-kit generate` the migrations straight out of the single file. Plus, it'll walk you through which columns you want to rename, which you want to make new, etc. Slick.
|
||||||
|
|
||||||
|
## But first, a detour...
|
||||||
|
|
||||||
|
I guess last time I had set up a schema in `packages/db/schema.ts`, and the migrations were in `packages/db/drizzle` -- I felt it was better to rename these:
|
||||||
|
|
||||||
|
- Schemas in their own directory (`schema`)
|
||||||
|
- Migrations called `migrations`, not `drizzle`
|
||||||
|
|
||||||
|
These changes required editing the front matter of a few Drizzle ts files, which I'm sure you can figure out for yourself.
|
||||||
|
|
||||||
|
Then I edited `day.ts` and prepared to generate and run the migrations.
|
||||||
|
|
||||||
|
This was the harder part that I do want to document:
|
||||||
|
|
||||||
|
### 1. Why won't the db generate command work
|
||||||
|
|
||||||
|
After changing the "events" schema I had started with last time to a "days" schema -- mainly to see if the db could migrate from one schema to another conflicting one -- I wasn't able to run the generate command:
|
||||||
|
|
||||||
|
```
|
||||||
|
pnpm drizzle-kit generate
|
||||||
|
```
|
||||||
|
|
||||||
|
`drizzle-kit` wasn't in the PATH, which was actually irrelevant, because I wanted to invoke this using `pnpm db:generate` the way I was able to run `pnpm db:migrate` and `pnpm db:studio`. Why wasn't it working?
|
||||||
|
|
||||||
|
The answer involved two steps. First, I had to add in `packages/db/package.json` a script:
|
||||||
|
|
||||||
|
```js
|
||||||
|
"scripts": {
|
||||||
|
"generate": "drizzle-kit generate"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
which was obvious. What was NOT obvious was that the `db:___` syntax wasn't filtering into the db package for me, it was just already defined for `migrate` and `studio` in the root level package.json. Added `db:generate` in there and everything worked great.
|
||||||
|
|
||||||
|
```js
|
||||||
|
"scripts": {
|
||||||
|
"build": "turbo build",
|
||||||
|
"dev": "turbo dev",
|
||||||
|
...
|
||||||
|
"db:generate": "pnpm --filter @lifetracker/db generate",
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, why not have this somehow alias to the one in the `packages/db/package.json` file? IDK, but the migrate and studio ones were written this way, so fuck it.
|
||||||
|
|
||||||
|
### 2. Adding "db:studio" to the dev pipeline in Turbo
|
||||||
|
|
||||||
|
With the migration ostensibly done, I wanted to see the glorious new table definition in the Drizzle Studio, but despite having run `pnpm run dev`, it wasn't running. How could I get it to run alongside?
|
||||||
|
|
||||||
|
This was pretty cool. I changed this in `turbo.json` at the project root:
|
||||||
|
|
||||||
|
```js
|
||||||
|
"dev": {
|
||||||
|
"dependsOn": ["^dev"], # This is the key
|
||||||
|
"cache": false,
|
||||||
|
"persistent": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
... and in the db package's `package.json`, I added:
|
||||||
|
|
||||||
|
```js
|
||||||
|
"scripts": {
|
||||||
|
...
|
||||||
|
"dev": "drizzle-kit studio",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This means that now when I run "pnpm dev" from the project root, along with Docusaurus (this shit) and the actual web app, I get the Drizzle Studio page simultaneously. So cool!
|
||||||
|
|
||||||
|
## Can we actually do something now?
|
||||||
|
|
||||||
@ -4,7 +4,7 @@ import type * as Preset from '@docusaurus/preset-classic';
|
|||||||
|
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
title: 'Lifetracker Docs',
|
title: 'Lifetracker Docs',
|
||||||
tagline: 'Dinosaurs are cool',
|
tagline: 'Tracking the life of the life tracker',
|
||||||
favicon: 'img/favicon.ico',
|
favicon: 'img/favicon.ico',
|
||||||
|
|
||||||
// Set the production url of your site here
|
// Set the production url of your site here
|
||||||
@ -93,8 +93,8 @@ const config: Config = {
|
|||||||
title: 'Docs',
|
title: 'Docs',
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
label: 'Tutorial',
|
label: 'Dev Environment',
|
||||||
to: '/docs/intro',
|
to: '/docs/category/how-i-built-this',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import Heading from '@theme/Heading';
|
|||||||
import styles from './index.module.css';
|
import styles from './index.module.css';
|
||||||
|
|
||||||
function HomepageHeader() {
|
function HomepageHeader() {
|
||||||
const {siteConfig} = useDocusaurusContext();
|
const { siteConfig } = useDocusaurusContext();
|
||||||
return (
|
return (
|
||||||
<header className={clsx('hero hero--primary', styles.heroBanner)}>
|
<header className={clsx('hero hero--primary', styles.heroBanner)}>
|
||||||
<div className="container">
|
<div className="container">
|
||||||
@ -19,8 +19,8 @@ function HomepageHeader() {
|
|||||||
<div className={styles.buttons}>
|
<div className={styles.buttons}>
|
||||||
<Link
|
<Link
|
||||||
className="button button--secondary button--lg"
|
className="button button--secondary button--lg"
|
||||||
to="/docs/intro">
|
to="/docs/category/how-i-built-this">
|
||||||
Docusaurus Tutorial - 5min ⏱️
|
Jump on in
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -29,7 +29,7 @@ function HomepageHeader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Home(): JSX.Element {
|
export default function Home(): JSX.Element {
|
||||||
const {siteConfig} = useDocusaurusContext();
|
const { siteConfig } = useDocusaurusContext();
|
||||||
return (
|
return (
|
||||||
<Layout
|
<Layout
|
||||||
title={`Hello from ${siteConfig.title}`}
|
title={`Hello from ${siteConfig.title}`}
|
||||||
|
|||||||
@ -6,13 +6,14 @@
|
|||||||
"dev": "turbo dev",
|
"dev": "turbo dev",
|
||||||
"lint": "turbo lint",
|
"lint": "turbo lint",
|
||||||
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
|
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
|
||||||
|
"db:generate": "pnpm --filter @lifetracker/db generate",
|
||||||
"db:studio": "pnpm --filter @lifetracker/db studio",
|
"db:studio": "pnpm --filter @lifetracker/db studio",
|
||||||
"db:migrate": "pnpm --filter @lifetracker/db run migrate"
|
"db:migrate": "pnpm --filter @lifetracker/db run migrate"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.3.3",
|
||||||
"turbo": "^2.1.3",
|
"turbo": "^2.2.3",
|
||||||
"typescript": "^5.4.5"
|
"typescript": "^5.6.3"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.10.0",
|
"packageManager": "pnpm@9.10.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@ -5,8 +5,8 @@ const databaseURL = "./lifetracker.db";
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
dialect: "sqlite",
|
dialect: "sqlite",
|
||||||
schema: "./schema.ts",
|
schema: "./schema",
|
||||||
out: "./drizzle",
|
out: "./migrations",
|
||||||
dbCredentials: {
|
dbCredentials: {
|
||||||
url: databaseURL,
|
url: databaseURL,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import "dotenv/config";
|
import "dotenv/config";
|
||||||
import { drizzle } from "drizzle-orm/better-sqlite3";
|
import { drizzle } from "drizzle-orm/better-sqlite3";
|
||||||
import Database from "better-sqlite3";
|
import Database from "better-sqlite3";
|
||||||
import * as schema from "./schema";
|
import * as schema from "./schema/day";
|
||||||
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,10 @@ import Database from "better-sqlite3";
|
|||||||
import { ExtractTablesWithRelations } from "drizzle-orm";
|
import { ExtractTablesWithRelations } from "drizzle-orm";
|
||||||
import { SQLiteTransaction } from "drizzle-orm/sqlite-core";
|
import { SQLiteTransaction } from "drizzle-orm/sqlite-core";
|
||||||
|
|
||||||
import * as schema from "./schema";
|
import * as schema from "./schema/day";
|
||||||
|
|
||||||
export { db } from "./drizzle";
|
export { db } from "./drizzle";
|
||||||
export * as schema from "./schema";
|
export * as schema from "./schema/day";
|
||||||
export { SqliteError } from "better-sqlite3";
|
export { SqliteError } from "better-sqlite3";
|
||||||
|
|
||||||
// This is exported here to avoid leaking better-sqlite types outside of this package.
|
// This is exported here to avoid leaking better-sqlite types outside of this package.
|
||||||
|
|||||||
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
import { db } from "./drizzle";
|
import { db } from "./drizzle";
|
||||||
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
||||||
|
|
||||||
migrate(db, { migrationsFolder: "./drizzle" });
|
migrate(db, { migrationsFolder: "./migrations" });
|
||||||
|
|||||||
5
packages/db/migrations/0001_hard_lionheart.sql
Normal file
5
packages/db/migrations/0001_hard_lionheart.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE `events` RENAME TO `days`;--> statement-breakpoint
|
||||||
|
ALTER TABLE `days` RENAME COLUMN `description` TO `comment`;--> statement-breakpoint
|
||||||
|
ALTER TABLE `days` ADD `mood` integer;--> statement-breakpoint
|
||||||
|
ALTER TABLE `days` ADD `date` text NOT NULL;--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX `days_date_unique` ON `days` (`date`);
|
||||||
66
packages/db/migrations/meta/0001_snapshot.json
Normal file
66
packages/db/migrations/meta/0001_snapshot.json
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"version": "6",
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"id": "6ad45ca2-1f2d-4e94-a8fd-b749a8577a61",
|
||||||
|
"prevId": "74097c41-1958-4fc8-8371-6e31b3071eb9",
|
||||||
|
"tables": {
|
||||||
|
"days": {
|
||||||
|
"name": "days",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": true
|
||||||
|
},
|
||||||
|
"mood": {
|
||||||
|
"name": "mood",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"date": {
|
||||||
|
"name": "date",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"comment": {
|
||||||
|
"name": "comment",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {
|
||||||
|
"days_date_unique": {
|
||||||
|
"name": "days_date_unique",
|
||||||
|
"columns": [
|
||||||
|
"date"
|
||||||
|
],
|
||||||
|
"isUnique": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enums": {},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {
|
||||||
|
"\"events\"": "\"days\""
|
||||||
|
},
|
||||||
|
"columns": {
|
||||||
|
"\"days\".\"description\"": "\"days\".\"comment\""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"internal": {
|
||||||
|
"indexes": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,6 +8,13 @@
|
|||||||
"when": 1728109876982,
|
"when": 1728109876982,
|
||||||
"tag": "0000_worried_may_parker",
|
"tag": "0000_worried_may_parker",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 1,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1731100507972,
|
||||||
|
"tag": "0001_hard_lionheart",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -5,6 +5,8 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"main": "index.ts",
|
"main": "index.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"dev": "drizzle-kit studio",
|
||||||
|
"generate": "drizzle-kit generate",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"migrate": "tsx migrate.ts",
|
"migrate": "tsx migrate.ts",
|
||||||
"studio": "drizzle-kit studio"
|
"studio": "drizzle-kit studio"
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
import {
|
|
||||||
sqliteTable,
|
|
||||||
integer,
|
|
||||||
text,
|
|
||||||
} from "drizzle-orm/sqlite-core";
|
|
||||||
|
|
||||||
export const events = sqliteTable("events", {
|
|
||||||
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
||||||
description: text("description").notNull(),
|
|
||||||
});
|
|
||||||
12
packages/db/schema/day.ts
Normal file
12
packages/db/schema/day.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import {
|
||||||
|
sqliteTable,
|
||||||
|
integer,
|
||||||
|
text,
|
||||||
|
} from "drizzle-orm/sqlite-core";
|
||||||
|
|
||||||
|
export const days = sqliteTable("days", {
|
||||||
|
id: integer("id").primaryKey({ autoIncrement: true }),
|
||||||
|
mood: integer("mood"),
|
||||||
|
date: text("date").notNull().unique(),
|
||||||
|
comment: text("comment").notNull(),
|
||||||
|
});
|
||||||
2058
pnpm-lock.yaml
generated
2058
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
23
turbo.json
23
turbo.json
@ -3,16 +3,29 @@
|
|||||||
"ui": "tui",
|
"ui": "tui",
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"build": {
|
"build": {
|
||||||
"dependsOn": ["^build"],
|
"dependsOn": [
|
||||||
"inputs": ["$TURBO_DEFAULT$", ".env*"],
|
"^build"
|
||||||
"outputs": [".next/**", "!.next/cache/**"]
|
],
|
||||||
|
"inputs": [
|
||||||
|
"$TURBO_DEFAULT$",
|
||||||
|
".env*"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
".next/**",
|
||||||
|
"!.next/cache/**"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
"dependsOn": ["^lint"]
|
"dependsOn": [
|
||||||
|
"^lint"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"dev": {
|
"dev": {
|
||||||
|
"dependsOn": [
|
||||||
|
"^dev"
|
||||||
|
],
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true
|
"persistent": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user