Browse Source

feat(db): add post_comments table for nested comments

Made-with: Cursor
main
npmrun 2 days ago
parent
commit
901667d317
  1. 37
      packages/drizzle-pkg/database/sqlite/schema/content.ts
  2. BIN
      packages/drizzle-pkg/db.sqlite
  3. 2
      packages/drizzle-pkg/lib/schema/content.ts
  4. 20
      packages/drizzle-pkg/migrations/0002_post-comments.sql
  5. 950
      packages/drizzle-pkg/migrations/meta/0002_snapshot.json
  6. 7
      packages/drizzle-pkg/migrations/meta/_journal.json

37
packages/drizzle-pkg/database/sqlite/schema/content.ts

@ -1,4 +1,11 @@
import { integer, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core"; import {
index,
integer,
sqliteTable,
text,
uniqueIndex,
type AnySQLiteColumn,
} from "drizzle-orm/sqlite-core";
import { users } from "./auth"; import { users } from "./auth";
@ -44,3 +51,31 @@ export const timelineEvents = sqliteTable("timeline_events", {
.$onUpdate(() => new Date()) .$onUpdate(() => new Date())
.notNull(), .notNull(),
}); });
export const postComments = sqliteTable(
"post_comments",
{
id: integer().primaryKey(),
postId: integer("post_id")
.notNull()
.references(() => posts.id, { onDelete: "cascade" }),
parentId: integer("parent_id").references((): AnySQLiteColumn => postComments.id),
authorUserId: integer("author_user_id").references(() => users.id, { onDelete: "set null" }),
guestDisplayName: text("guest_display_name"),
body: text().notNull(),
kind: text().notNull(),
deletedAt: integer("deleted_at", { mode: "timestamp_ms" }),
deletedByUserId: integer("deleted_by_user_id").references(() => users.id, {
onDelete: "set null",
}),
createdAt: integer("created_at", { mode: "timestamp_ms" }).defaultNow().notNull(),
updatedAt: integer("updated_at", { mode: "timestamp_ms" })
.defaultNow()
.$onUpdate(() => new Date())
.notNull(),
},
(table) => [
index("post_comments_post_id_idx").on(table.postId),
index("post_comments_parent_id_idx").on(table.parentId),
],
);

BIN
packages/drizzle-pkg/db.sqlite

Binary file not shown.

2
packages/drizzle-pkg/lib/schema/content.ts

@ -1 +1 @@
export { posts, timelineEvents } from "../../database/sqlite/schema/content"; export { postComments, posts, timelineEvents } from "../../database/sqlite/schema/content";

20
packages/drizzle-pkg/migrations/0002_post-comments.sql

@ -0,0 +1,20 @@
CREATE TABLE `post_comments` (
`id` integer PRIMARY KEY NOT NULL,
`post_id` integer NOT NULL,
`parent_id` integer,
`author_user_id` integer,
`guest_display_name` text,
`body` text NOT NULL,
`kind` text NOT NULL,
`deleted_at` integer,
`deleted_by_user_id` integer,
`created_at` integer DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer)) NOT NULL,
`updated_at` integer DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer)) NOT NULL,
FOREIGN KEY (`post_id`) REFERENCES `posts`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`parent_id`) REFERENCES `post_comments`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`author_user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE set null,
FOREIGN KEY (`deleted_by_user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE set null
);
--> statement-breakpoint
CREATE INDEX `post_comments_post_id_idx` ON `post_comments` (`post_id`);--> statement-breakpoint
CREATE INDEX `post_comments_parent_id_idx` ON `post_comments` (`parent_id`);

950
packages/drizzle-pkg/migrations/meta/0002_snapshot.json

@ -0,0 +1,950 @@
{
"version": "6",
"dialect": "sqlite",
"id": "ea7fcedb-76a9-4158-b247-2a5f162b1bdd",
"prevId": "66f33657-5926-4ac6-a196-2d142081b192",
"tables": {
"sessions": {
"name": "sessions",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"expires_at": {
"name": "expires_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
}
},
"indexes": {
"sessions_user_id_idx": {
"name": "sessions_user_id_idx",
"columns": [
"user_id"
],
"isUnique": false
}
},
"foreignKeys": {
"sessions_user_id_users_id_fk": {
"name": "sessions_user_id_users_id_fk",
"tableFrom": "sessions",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"users": {
"name": "users",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"nickname": {
"name": "nickname",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"avatar": {
"name": "avatar",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"role": {
"name": "role",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'user'"
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'active'"
},
"public_slug": {
"name": "public_slug",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"bio_markdown": {
"name": "bio_markdown",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"bio_visibility": {
"name": "bio_visibility",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'private'"
},
"social_links_json": {
"name": "social_links_json",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'[]'"
},
"avatar_visibility": {
"name": "avatar_visibility",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'private'"
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
}
},
"indexes": {
"users_username_unique": {
"name": "users_username_unique",
"columns": [
"username"
],
"isUnique": true
},
"users_public_slug_unique": {
"name": "users_public_slug_unique",
"columns": [
"public_slug"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"app_configs": {
"name": "app_configs",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"value_type": {
"name": "value_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"user_configs": {
"name": "user_configs",
"columns": {
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"key": {
"name": "key",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"value_type": {
"name": "value_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
}
},
"indexes": {
"user_configs_user_id_idx": {
"name": "user_configs_user_id_idx",
"columns": [
"user_id"
],
"isUnique": false
}
},
"foreignKeys": {
"user_configs_user_id_users_id_fk": {
"name": "user_configs_user_id_users_id_fk",
"tableFrom": "user_configs",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"user_configs_user_id_key_pk": {
"columns": [
"user_id",
"key"
],
"name": "user_configs_user_id_key_pk"
}
},
"uniqueConstraints": {},
"checkConstraints": {}
},
"post_comments": {
"name": "post_comments",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"post_id": {
"name": "post_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"parent_id": {
"name": "parent_id",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"author_user_id": {
"name": "author_user_id",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"guest_display_name": {
"name": "guest_display_name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"body": {
"name": "body",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"kind": {
"name": "kind",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"deleted_at": {
"name": "deleted_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"deleted_by_user_id": {
"name": "deleted_by_user_id",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
}
},
"indexes": {
"post_comments_post_id_idx": {
"name": "post_comments_post_id_idx",
"columns": [
"post_id"
],
"isUnique": false
},
"post_comments_parent_id_idx": {
"name": "post_comments_parent_id_idx",
"columns": [
"parent_id"
],
"isUnique": false
}
},
"foreignKeys": {
"post_comments_post_id_posts_id_fk": {
"name": "post_comments_post_id_posts_id_fk",
"tableFrom": "post_comments",
"tableTo": "posts",
"columnsFrom": [
"post_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"post_comments_parent_id_post_comments_id_fk": {
"name": "post_comments_parent_id_post_comments_id_fk",
"tableFrom": "post_comments",
"tableTo": "post_comments",
"columnsFrom": [
"parent_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"post_comments_author_user_id_users_id_fk": {
"name": "post_comments_author_user_id_users_id_fk",
"tableFrom": "post_comments",
"tableTo": "users",
"columnsFrom": [
"author_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"post_comments_deleted_by_user_id_users_id_fk": {
"name": "post_comments_deleted_by_user_id_users_id_fk",
"tableFrom": "post_comments",
"tableTo": "users",
"columnsFrom": [
"deleted_by_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"posts": {
"name": "posts",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"slug": {
"name": "slug",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"body_markdown": {
"name": "body_markdown",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"excerpt": {
"name": "excerpt",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"cover_url": {
"name": "cover_url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"tags_json": {
"name": "tags_json",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'[]'"
},
"published_at": {
"name": "published_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"visibility": {
"name": "visibility",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'private'"
},
"share_token": {
"name": "share_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
}
},
"indexes": {
"posts_user_id_slug_unique": {
"name": "posts_user_id_slug_unique",
"columns": [
"user_id",
"slug"
],
"isUnique": true
}
},
"foreignKeys": {
"posts_user_id_users_id_fk": {
"name": "posts_user_id_users_id_fk",
"tableFrom": "posts",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"timeline_events": {
"name": "timeline_events",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"occurred_on": {
"name": "occurred_on",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"body_markdown": {
"name": "body_markdown",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"link_url": {
"name": "link_url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"visibility": {
"name": "visibility",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'private'"
},
"share_token": {
"name": "share_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
}
},
"indexes": {},
"foreignKeys": {
"timeline_events_user_id_users_id_fk": {
"name": "timeline_events_user_id_users_id_fk",
"tableFrom": "timeline_events",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"rss_feeds": {
"name": "rss_feeds",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"feed_url": {
"name": "feed_url",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"site_url": {
"name": "site_url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"last_fetched_at": {
"name": "last_fetched_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"last_error": {
"name": "last_error",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"poll_interval_minutes": {
"name": "poll_interval_minutes",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
}
},
"indexes": {
"rss_feeds_user_id_feed_url_unique": {
"name": "rss_feeds_user_id_feed_url_unique",
"columns": [
"user_id",
"feed_url"
],
"isUnique": true
}
},
"foreignKeys": {
"rss_feeds_user_id_users_id_fk": {
"name": "rss_feeds_user_id_users_id_fk",
"tableFrom": "rss_feeds",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"rss_items": {
"name": "rss_items",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"feed_id": {
"name": "feed_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"guid": {
"name": "guid",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"canonical_url": {
"name": "canonical_url",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"summary": {
"name": "summary",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"content_snippet": {
"name": "content_snippet",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"author": {
"name": "author",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"published_at": {
"name": "published_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"visibility": {
"name": "visibility",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'private'"
},
"share_token": {
"name": "share_token",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))"
}
},
"indexes": {
"rss_items_feed_id_guid_unique": {
"name": "rss_items_feed_id_guid_unique",
"columns": [
"feed_id",
"guid"
],
"isUnique": true,
"where": "\"rss_items\".\"guid\" IS NOT NULL"
}
},
"foreignKeys": {
"rss_items_user_id_users_id_fk": {
"name": "rss_items_user_id_users_id_fk",
"tableFrom": "rss_items",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"rss_items_feed_id_rss_feeds_id_fk": {
"name": "rss_items_feed_id_rss_feeds_id_fk",
"tableFrom": "rss_items",
"tableTo": "rss_feeds",
"columnsFrom": [
"feed_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

7
packages/drizzle-pkg/migrations/meta/_journal.json

@ -15,6 +15,13 @@
"when": 1776457621565, "when": 1776457621565,
"tag": "0001_add-multitenant-content-rss", "tag": "0001_add-multitenant-content-rss",
"breakpoints": true "breakpoints": true
},
{
"idx": 2,
"version": "6",
"when": 1776498812973,
"tag": "0002_post-comments",
"breakpoints": true
} }
] ]
} }
Loading…
Cancel
Save