diff --git a/drizzle/0000_burly_katie_power.sql b/drizzle/0000_windy_wrecking_crew.sql similarity index 83% rename from drizzle/0000_burly_katie_power.sql rename to drizzle/0000_windy_wrecking_crew.sql index 1e7c7fb..df2373b 100644 --- a/drizzle/0000_burly_katie_power.sql +++ b/drizzle/0000_windy_wrecking_crew.sql @@ -13,7 +13,7 @@ CREATE TABLE IF NOT EXISTS "accounts" ( CONSTRAINT "accounts_provider_provider_account_id_pk" PRIMARY KEY("provider","provider_account_id") ); --> statement-breakpoint -CREATE TABLE IF NOT EXISTS "images" ( +CREATE TABLE IF NOT EXISTS "posts" ( "id" varchar(255) PRIMARY KEY NOT NULL, "slug" varchar(255) NOT NULL, "title" varchar(256), @@ -23,7 +23,7 @@ CREATE TABLE IF NOT EXISTS "images" ( "created_by" varchar(255) NOT NULL, "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, "updated_at" timestamp with time zone, - CONSTRAINT "images_slug_unique" UNIQUE("slug") + CONSTRAINT "posts_slug_unique" UNIQUE("slug") ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "sessions" ( @@ -55,7 +55,7 @@ EXCEPTION END $$; --> statement-breakpoint DO $$ BEGIN - ALTER TABLE "images" ADD CONSTRAINT "images_created_by_users_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action; + ALTER TABLE "posts" ADD CONSTRAINT "posts_created_by_users_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; @@ -67,6 +67,6 @@ EXCEPTION END $$; --> statement-breakpoint CREATE INDEX IF NOT EXISTS "account_user_id_idx" ON "accounts" USING btree ("user_id");--> statement-breakpoint -CREATE INDEX IF NOT EXISTS "image_user_id_idx" ON "images" USING btree ("created_by");--> statement-breakpoint -CREATE INDEX IF NOT EXISTS "image_slug_idx" ON "images" USING btree ("slug");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "image_user_id_idx" ON "posts" USING btree ("created_by");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "image_slug_idx" ON "posts" USING btree ("slug");--> statement-breakpoint CREATE INDEX IF NOT EXISTS "session_user_id_idx" ON "sessions" USING btree ("user_id"); \ No newline at end of file diff --git a/drizzle/0001_warm_jimmy_woo.sql b/drizzle/0001_warm_jimmy_woo.sql new file mode 100644 index 0000000..7d738d5 --- /dev/null +++ b/drizzle/0001_warm_jimmy_woo.sql @@ -0,0 +1,13 @@ +CREATE TABLE IF NOT EXISTS "votes" ( + "id" varchar(255) PRIMARY KEY NOT NULL, + "up" boolean DEFAULT true NOT NULL, + "created_by" varchar(255) NOT NULL, + "created_at" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + "updated_at" timestamp with time zone +); +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "votes" ADD CONSTRAINT "votes_created_by_users_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/drizzle/0002_sloppy_starfox.sql b/drizzle/0002_sloppy_starfox.sql new file mode 100644 index 0000000..de2a245 --- /dev/null +++ b/drizzle/0002_sloppy_starfox.sql @@ -0,0 +1,6 @@ +ALTER TABLE "votes" ADD COLUMN "post_id" varchar(255) NOT NULL;--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "votes" ADD CONSTRAINT "votes_post_id_posts_id_fk" FOREIGN KEY ("post_id") REFERENCES "public"."posts"("id") ON DELETE no action ON UPDATE no action; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/drizzle/meta/0000_snapshot.json b/drizzle/meta/0000_snapshot.json index 390a6e7..648f48c 100644 --- a/drizzle/meta/0000_snapshot.json +++ b/drizzle/meta/0000_snapshot.json @@ -1,5 +1,5 @@ { - "id": "6010a064-33aa-404b-b933-c4ca1f1c415d", + "id": "df0e1372-accb-4875-885d-c19970e69eae", "prevId": "00000000-0000-0000-0000-000000000000", "version": "7", "dialect": "postgresql", @@ -118,8 +118,8 @@ }, "uniqueConstraints": {} }, - "public.images": { - "name": "images", + "public.posts": { + "name": "posts", "schema": "", "columns": { "id": { @@ -211,9 +211,9 @@ } }, "foreignKeys": { - "images_created_by_users_id_fk": { - "name": "images_created_by_users_id_fk", - "tableFrom": "images", + "posts_created_by_users_id_fk": { + "name": "posts_created_by_users_id_fk", + "tableFrom": "posts", "tableTo": "users", "columnsFrom": [ "created_by" @@ -227,8 +227,8 @@ }, "compositePrimaryKeys": {}, "uniqueConstraints": { - "images_slug_unique": { - "name": "images_slug_unique", + "posts_slug_unique": { + "name": "posts_slug_unique", "nullsNotDistinct": false, "columns": [ "slug" diff --git a/drizzle/meta/0001_snapshot.json b/drizzle/meta/0001_snapshot.json new file mode 100644 index 0000000..a8080ea --- /dev/null +++ b/drizzle/meta/0001_snapshot.json @@ -0,0 +1,445 @@ +{ + "id": "e8b4ac19-4d79-4886-ad5e-eb19f551efde", + "prevId": "df0e1372-accb-4875-885d-c19970e69eae", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.accounts": { + "name": "accounts", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "provider_account_id": { + "name": "provider_account_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "account_user_id_idx": { + "name": "account_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "accounts_user_id_users_id_fk": { + "name": "accounts_user_id_users_id_fk", + "tableFrom": "accounts", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "accounts_provider_provider_account_id_pk": { + "name": "accounts_provider_provider_account_id_pk", + "columns": [ + "provider", + "provider_account_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.posts": { + "name": "posts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "varchar(256)", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "filepath": { + "name": "filepath", + "type": "varchar(256)", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "image_user_id_idx": { + "name": "image_user_id_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "image_slug_idx": { + "name": "image_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "posts_created_by_users_id_fk": { + "name": "posts_created_by_users_id_fk", + "tableFrom": "posts", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "posts_slug_unique": { + "name": "posts_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + } + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "session_token": { + "name": "session_token", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "session_user_id_idx": { + "name": "session_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false, + "default": "CURRENT_TIMESTAMP" + }, + "image": { + "name": "image", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.verification_tokens": { + "name": "verification_tokens", + "schema": "", + "columns": { + "identifier": { + "name": "identifier", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verification_tokens_identifier_token_pk": { + "name": "verification_tokens_identifier_token_pk", + "columns": [ + "identifier", + "token" + ] + } + }, + "uniqueConstraints": {} + }, + "public.votes": { + "name": "votes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "up": { + "name": "up", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_by": { + "name": "created_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "votes_created_by_users_id_fk": { + "name": "votes_created_by_users_id_fk", + "tableFrom": "votes", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/0002_snapshot.json b/drizzle/meta/0002_snapshot.json new file mode 100644 index 0000000..a7ee633 --- /dev/null +++ b/drizzle/meta/0002_snapshot.json @@ -0,0 +1,464 @@ +{ + "id": "2ce7d201-995a-4c67-9041-93767b913d60", + "prevId": "e8b4ac19-4d79-4886-ad5e-eb19f551efde", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.accounts": { + "name": "accounts", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "provider_account_id": { + "name": "provider_account_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "account_user_id_idx": { + "name": "account_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "accounts_user_id_users_id_fk": { + "name": "accounts_user_id_users_id_fk", + "tableFrom": "accounts", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "accounts_provider_provider_account_id_pk": { + "name": "accounts_provider_provider_account_id_pk", + "columns": [ + "provider", + "provider_account_id" + ] + } + }, + "uniqueConstraints": {} + }, + "public.posts": { + "name": "posts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "varchar(256)", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "tags": { + "name": "tags", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "filepath": { + "name": "filepath", + "type": "varchar(256)", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "image_user_id_idx": { + "name": "image_user_id_idx", + "columns": [ + { + "expression": "created_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "image_slug_idx": { + "name": "image_slug_idx", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "posts_created_by_users_id_fk": { + "name": "posts_created_by_users_id_fk", + "tableFrom": "posts", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "posts_slug_unique": { + "name": "posts_slug_unique", + "nullsNotDistinct": false, + "columns": [ + "slug" + ] + } + } + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "session_token": { + "name": "session_token", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "session_user_id_idx": { + "name": "session_user_id_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false, + "default": "CURRENT_TIMESTAMP" + }, + "image": { + "name": "image", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.verification_tokens": { + "name": "verification_tokens", + "schema": "", + "columns": { + "identifier": { + "name": "identifier", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "verification_tokens_identifier_token_pk": { + "name": "verification_tokens_identifier_token_pk", + "columns": [ + "identifier", + "token" + ] + } + }, + "uniqueConstraints": {} + }, + "public.votes": { + "name": "votes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "post_id": { + "name": "post_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "up": { + "name": "up", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_by": { + "name": "created_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "votes_post_id_posts_id_fk": { + "name": "votes_post_id_posts_id_fk", + "tableFrom": "votes", + "tableTo": "posts", + "columnsFrom": [ + "post_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "votes_created_by_users_id_fk": { + "name": "votes_created_by_users_id_fk", + "tableFrom": "votes", + "tableTo": "users", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json index b5e9169..5a1dfc4 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -5,8 +5,22 @@ { "idx": 0, "version": "7", - "when": 1726843311417, - "tag": "0000_burly_katie_power", + "when": 1726870110731, + "tag": "0000_windy_wrecking_crew", + "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1726870450874, + "tag": "0001_warm_jimmy_woo", + "breakpoints": true + }, + { + "idx": 2, + "version": "7", + "when": 1726870854367, + "tag": "0002_sloppy_starfox", "breakpoints": true } ] diff --git a/scripts/scaffold.sql b/scripts/scaffold.sql index c9f96f8..cdb00dd 100644 --- a/scripts/scaffold.sql +++ b/scripts/scaffold.sql @@ -1,12 +1,12 @@ -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('974248ec-ae31-4c1a-900d-348432e16e90', 'Frasier "directs" Niles', 'Ham Radio', '{}', '974248ec-ae31-4c1a-900d-348432e16e90.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:26:51.350362 +00:00', '2024-09-18 15:26:51.639000 +00:00', 'frasier-directs-niles'); -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('18fac61f-d2c4-4248-b74b-5d23e8717bbc', 'Frasier groaning.', 'Frasier & Niles in Nervosa', '{}', '18fac61f-d2c4-4248-b74b-5d23e8717bbc.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:46.438441 +00:00', '2024-09-18 15:27:46.477000 +00:00', 'frasier-groaning'); -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('56e89352-aa69-4a9e-92c4-5eb3e8e94703', 'Frasier tasting caviar', 'From Roe to Perdition S10E18 ', '{}', '56e89352-aa69-4a9e-92c4-5eb3e8e94703.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:28.599836 +00:00', '2024-09-18 15:27:28.632000 +00:00', 'frasier-tasting-caviar'); -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('38d3e400-20a3-49be-bf8f-5c4c77ab3a9f', 'Niles gets a class of champagne in the face', 'From Voyage of the Damned', '{}', '38d3e400-20a3-49be-bf8f-5c4c77ab3a9f.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:01.933852 +00:00', '2024-09-18 15:27:01.967000 +00:00', 'niles-gets-a-class-of-champagne-in-the-face'); -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('4aa77fab-cfe4-4f5d-ba62-c674b43b09c8', 'I miss being unapproachable', 'From Good Grief', '{}', '4aa77fab-cfe4-4f5d-ba62-c674b43b09c8.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:18.617006 +00:00', '2024-09-18 15:27:18.651000 +00:00', 'i-miss-being-unapproachable'); -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('062edc3f-2d3c-4d97-a569-f41804d6d352', 'I''m having one now', 'Niles has never had an unexpressed thought', '{niles,frasier}', '062edc3f-2d3c-4d97-a569-f41804d6d352.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:59.258519 +00:00', '2024-09-18 15:27:59.283000 +00:00', 'i-m-having-one-now'); -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('ced6dc13-10b4-43d7-8072-0db2091840d7', 'Wounded!!!', 'Frasier is wounded', '{frasier,wounded}', 'ced6dc13-10b4-43d7-8072-0db2091840d7.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:37.875584 +00:00', '2024-09-18 15:27:37.914000 +00:00', 'wounded'); -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('13c54e08-2fd6-4810-982f-14b701e38b5f', 'Rrrrreally.', 'Guy checks out Niles'' bottom', '{}', '13c54e08-2fd6-4810-982f-14b701e38b5f.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:13.414832 +00:00', '2024-09-18 15:27:13.442000 +00:00', 'rrrrreally'); -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('d23df48f-2b99-4b29-90fd-2f3cff205010', 'Successful High Five', 'Niles & Frasier successfully complete a high five (including behind the back down low).', '{}', 'd23df48f-2b99-4b29-90fd-2f3cff205010.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:51.131650 +00:00', '2024-09-18 15:27:51.152000 +00:00', 'successful-high-five'); -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('0ccfccd4-c24f-42a0-9864-2cb8d230bb16', 'Niles clapping', 'Niles is excited', '{}', '0ccfccd4-c24f-42a0-9864-2cb8d230bb16.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:33.156638 +00:00', '2024-09-18 15:27:33.220000 +00:00', 'niles-clapping'); -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('4a208725-453d-4d0c-b620-cc82b7192ea8', 'I just want to die!!', '', '{}', '4a208725-453d-4d0c-b620-cc82b7192ea8.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:07.374464 +00:00', '2024-09-18 15:27:07.396000 +00:00', 'i-just-want-to-die'); -INSERT INTO public.images (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('4a2a52a2-85eb-417c-bdb8-a1d0101df17f', 'Some boys go to college.', 'Oh, some boys go to college, but we think they''re all wussies, cuz they get all the knowledge, and we get all the...', '{}', '4a2a52a2-85eb-417c-bdb8-a1d0101df17f.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:42.138300 +00:00', '2024-09-18 15:27:42.175000 +00:00', 'some-boys-go-to-college'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('974248ec-ae31-4c1a-900d-348432e16e90', 'Frasier "directs" Niles', 'Ham Radio', '{}', '974248ec-ae31-4c1a-900d-348432e16e90.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:26:51.350362 +00:00', '2024-09-18 15:26:51.639000 +00:00', 'frasier-directs-niles'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('18fac61f-d2c4-4248-b74b-5d23e8717bbc', 'Frasier groaning.', 'Frasier & Niles in Nervosa', '{}', '18fac61f-d2c4-4248-b74b-5d23e8717bbc.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:46.438441 +00:00', '2024-09-18 15:27:46.477000 +00:00', 'frasier-groaning'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('56e89352-aa69-4a9e-92c4-5eb3e8e94703', 'Frasier tasting caviar', 'From Roe to Perdition S10E18 ', '{}', '56e89352-aa69-4a9e-92c4-5eb3e8e94703.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:28.599836 +00:00', '2024-09-18 15:27:28.632000 +00:00', 'frasier-tasting-caviar'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('38d3e400-20a3-49be-bf8f-5c4c77ab3a9f', 'Niles gets a class of champagne in the face', 'From Voyage of the Damned', '{}', '38d3e400-20a3-49be-bf8f-5c4c77ab3a9f.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:01.933852 +00:00', '2024-09-18 15:27:01.967000 +00:00', 'niles-gets-a-class-of-champagne-in-the-face'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('4aa77fab-cfe4-4f5d-ba62-c674b43b09c8', 'I miss being unapproachable', 'From Good Grief', '{}', '4aa77fab-cfe4-4f5d-ba62-c674b43b09c8.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:18.617006 +00:00', '2024-09-18 15:27:18.651000 +00:00', 'i-miss-being-unapproachable'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('062edc3f-2d3c-4d97-a569-f41804d6d352', 'I''m having one now', 'Niles has never had an unexpressed thought', '{niles,frasier}', '062edc3f-2d3c-4d97-a569-f41804d6d352.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:59.258519 +00:00', '2024-09-18 15:27:59.283000 +00:00', 'i-m-having-one-now'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('ced6dc13-10b4-43d7-8072-0db2091840d7', 'Wounded!!!', 'Frasier is wounded', '{frasier,wounded}', 'ced6dc13-10b4-43d7-8072-0db2091840d7.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:37.875584 +00:00', '2024-09-18 15:27:37.914000 +00:00', 'wounded'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('13c54e08-2fd6-4810-982f-14b701e38b5f', 'Rrrrreally.', 'Guy checks out Niles'' bottom', '{}', '13c54e08-2fd6-4810-982f-14b701e38b5f.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:13.414832 +00:00', '2024-09-18 15:27:13.442000 +00:00', 'rrrrreally'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('d23df48f-2b99-4b29-90fd-2f3cff205010', 'Successful High Five', 'Niles & Frasier successfully complete a high five (including behind the back down low).', '{}', 'd23df48f-2b99-4b29-90fd-2f3cff205010.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:51.131650 +00:00', '2024-09-18 15:27:51.152000 +00:00', 'successful-high-five'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('0ccfccd4-c24f-42a0-9864-2cb8d230bb16', 'Niles clapping', 'Niles is excited', '{}', '0ccfccd4-c24f-42a0-9864-2cb8d230bb16.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:33.156638 +00:00', '2024-09-18 15:27:33.220000 +00:00', 'niles-clapping'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('4a208725-453d-4d0c-b620-cc82b7192ea8', 'I just want to die!!', '', '{}', '4a208725-453d-4d0c-b620-cc82b7192ea8.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:07.374464 +00:00', '2024-09-18 15:27:07.396000 +00:00', 'i-just-want-to-die'); +INSERT INTO public.posts (id, title, description, tags, filepath, created_by, created_at, updated_at, slug) VALUES ('4a2a52a2-85eb-417c-bdb8-a1d0101df17f', 'Some boys go to college.', 'Oh, some boys go to college, but we think they''re all wussies, cuz they get all the knowledge, and we get all the...', '{}', '4a2a52a2-85eb-417c-bdb8-a1d0101df17f.gif', '6c98e4e0-873c-4bd0-a059-93177709eddd', '2024-09-18 15:27:42.138300 +00:00', '2024-09-18 15:27:42.175000 +00:00', 'some-boys-go-to-college'); diff --git a/src/app/api/upload/post/route.ts b/src/app/api/upload/post/route.ts index f73c5eb..69ef082 100644 --- a/src/app/api/upload/post/route.ts +++ b/src/app/api/upload/post/route.ts @@ -5,7 +5,7 @@ import { type NextRequest, NextResponse } from "next/server"; import fs from "fs"; import path from "path"; import { db } from "@/server/db"; -import { images } from "@/server/db/schema"; +import { posts } from "@/server/db/schema"; import { eq } from "drizzle-orm"; export async function POST(request: NextRequest) { @@ -36,7 +36,7 @@ export async function POST(request: NextRequest) { fs.writeFileSync(path.resolve(env.UPLOAD_PATH, filePath), buffer); - await db.update(images).set({ filePath }).where(eq(images.id, id)); + await db.update(posts).set({ filePath }).where(eq(posts.id, id)); return NextResponse.json({ success: true, diff --git a/src/app/page.tsx b/src/app/page.tsx index 7b7cb6d..0ffbd49 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,5 +1,5 @@ import LandingPage from "@/components/pages/landing-page"; -import { TrendingImages } from "@/components/trending-images"; +import { TrendingPosts } from "@/components/trending-posts"; import { getServerAuthSession } from "@/server/auth"; import { api, HydrateClient } from "@/trpc/server"; @@ -9,7 +9,7 @@ export default async function Home() { return ( - {session?.user ? : } + {session?.user ? : } ); } diff --git a/src/components/pages/landing-page.tsx b/src/components/pages/landing-page.tsx index 2115222..129da63 100644 --- a/src/components/pages/landing-page.tsx +++ b/src/components/pages/landing-page.tsx @@ -1,15 +1,14 @@ import React from "react"; +import { TrendingPosts } from "@/components/trending-posts"; +import { api, HydrateClient } from "@/trpc/server"; + +const LandingPage: React.FC = async () => { + void api.post.getTrending.prefetch(); -const LandingPage: React.FC = () => { return ( -
-
-

- Contains - Gifs -

-
-
+ + + ); }; diff --git a/src/components/pages/post/post-actions.tsx b/src/components/pages/post/post-actions.tsx index d51994d..eefddf4 100644 --- a/src/components/pages/post/post-actions.tsx +++ b/src/components/pages/post/post-actions.tsx @@ -2,29 +2,47 @@ import { Post } from "@/lib/models/post"; import React from "react"; import ActionButton from "@/components/widgets/action-button"; import { Icons } from "@/components/icons"; +import { api } from "@/trpc/react"; type PostActionsProps = { post: Post; }; const PostActions: React.FC = ({ post }) => { + const vote = api.post.vote.useMutation(); + const voteCount = api.post.getVoteCount.useQuery({ slug: post.slug }); return (
{}} - icon={} + action={async () => { + await vote.mutateAsync({ slug: post.slug, up: true }); + voteCount.refetch(); + }} + icon={} /> -
{post.likes}
+
+ {voteCount.data ? ( + voteCount.data.toString() + ) : ( + + )} +
{}} - icon={} + action={async () => { + await vote.mutateAsync({ slug: post.slug, up: false }); + voteCount.refetch(); + }} + icon={} /> {}} - icon={} + action={async () => { + await vote.mutateAsync({ slug: post.slug, up: false }); + voteCount.refetch(); + }} + icon={} />
); diff --git a/src/components/trending-images.tsx b/src/components/trending-posts.tsx similarity index 77% rename from src/components/trending-images.tsx rename to src/components/trending-posts.tsx index a3e11d0..e79604c 100644 --- a/src/components/trending-images.tsx +++ b/src/components/trending-posts.tsx @@ -1,42 +1,42 @@ import { api } from "@/trpc/server"; import BlurIn from "./magicui/blur-in"; -import { Button } from "@/components/ui/button"; import Link from "next/link"; import { Icons } from "./icons"; import ActionButton from "./widgets/action-button"; +import { Post } from "@/lib/models/post"; const upvote = async () => { "use server"; - console.log("trending-images", "upvote"); + console.log("trending-posts", "upvote"); }; const downvote = async () => { "use server"; - console.log("trending-images", "downvote"); + console.log("trending-posts", "downvote"); }; -export const TrendingImages: React.FC = async () => { - const latestImages = await api.post.getTrending(); - return latestImages.length !== 0 ? ( +export const TrendingPosts: React.FC = async () => { + const trendingPosts = await api.post.getTrending(); + return trendingPosts.length !== 0 ? (
- {latestImages.map((image) => ( - + {trendingPosts.map((post: Post) => ( +
{image.description
- {image.title} + {post.title}
- {image.description} + {post.description}
diff --git a/src/server/api/routers/auth.ts b/src/server/api/routers/auth.ts index 0c4cdea..cdbffc8 100644 --- a/src/server/api/routers/auth.ts +++ b/src/server/api/routers/auth.ts @@ -8,7 +8,7 @@ export const authRouter = createTRPCRouter({ create: publicProcedure .input(z.object({ email: z.string().email(), password: z.string().min(5) })) .mutation(async ({ ctx, input }) => { - const profileImage = faker.image.avatar(); + const profileImage = faker.image.avatarGitHub(); const hashedPassword = await bcrypt.hash(input.password, 10); const user = await ctx.db.insert(users).values({ email: input.email, diff --git a/src/server/api/routers/post.ts b/src/server/api/routers/post.ts index d2c4d24..533a26c 100644 --- a/src/server/api/routers/post.ts +++ b/src/server/api/routers/post.ts @@ -5,38 +5,47 @@ import { } from "@/server/api/trpc"; import { slugifyWithCounter } from "@sindresorhus/slugify"; import { z } from "zod"; -import { images, users } from "@/server/db/schema"; +import { posts, users, votes } from "@/server/db/schema"; import { env } from "@/env"; -import { and, eq } from "drizzle-orm"; +import { and, eq, sql } from "drizzle-orm"; import { Post } from "@/lib/models/post"; export const postRouter = createTRPCRouter({ + getVoteCount: publicProcedure + .input(z.object({ slug: z.string() })) + .query(async ({ ctx, input }) => { + const count = await ctx.db + .execute(sql`SELECT SUM(CASE WHEN up = TRUE THEN 1 ELSE -1 END) + FROM public.votes v + WHERE v.post_id = (SELECT id FROM posts WHERE slug = ${input.slug})`); + return count[0]?.sum ?? '0'; + }), getBySlug: publicProcedure .input(z.object({ slug: z.string() })) .query(async ({ ctx, input }) => { - const image = ( + const post = ( await ctx.db .select() - .from(images) - .where(and(eq(images.slug, input.slug))) + .from(posts) + .where(and(eq(posts.slug, input.slug))) .limit(1) )[0]; - if (!image) { + if (!post) { throw new Error("Image not found"); } return { - slug: image.id, - title: image.title, - description: image.description, - tags: image.tags, - imageUrl: `/i/${image.filePath}`, + slug: post.slug, + title: post.title, + description: post.description, + tags: post.tags, + imageUrl: `/i/${post.filePath}`, likes: 0, dislikes: 0, } as Post; }), getTrending: publicProcedure.query(async ({ ctx }) => { - const trending = await ctx.db.query.images.findMany({ - orderBy: (images, { desc }) => [desc(images.createdAt)], + const trending = await ctx.db.query.posts.findMany({ + orderBy: (posts, { desc }) => [desc(posts.createdAt)], }); return ( trending.map((t) => { @@ -52,6 +61,38 @@ export const postRouter = createTRPCRouter({ }) ?? null ); }), + vote: protectedProcedure + .input(z.object({ slug: z.string(), up: z.boolean() })) + .mutation(async ({ ctx, input }) => { + const post = await ctx.db + .select() + .from(posts) + .where(eq(posts.slug, input.slug)) + .limit(1) + .then((results) => results[0]); + + if (!post) { + throw new Error("Post not found"); + } + + const vote = await ctx.db + .insert(votes) + .values({ + postId: post.id, + createdById: ctx.session.user.id, + up: input.up, + }) + .returning() + .then((results) => results[0]); + + if (!vote) { + throw new Error("Failed to register vote"); + } + + return { + success: true, + }; + }), create: protectedProcedure .input( z.object({ @@ -68,8 +109,8 @@ export const postRouter = createTRPCRouter({ slug = slugify(input.title); const existing = await ctx.db .select() - .from(images) - .where(and(eq(images.slug, slug))) + .from(posts) + .where(and(eq(posts.slug, slug))) .limit(1); if (!existing[0]) { found = true; @@ -77,7 +118,7 @@ export const postRouter = createTRPCRouter({ } while (!found); const post = await ctx.db - .insert(images) + .insert(posts) .values({ title: input.title, slug: slug, diff --git a/src/server/db/schema.ts b/src/server/db/schema.ts index 946eada..a579924 100644 --- a/src/server/db/schema.ts +++ b/src/server/db/schema.ts @@ -1,5 +1,6 @@ import { relations, sql } from "drizzle-orm"; import { + boolean, index, integer, pgTableCreator, @@ -13,8 +14,8 @@ import { type AdapterAccount } from "next-auth/adapters"; export const createTable = pgTableCreator((name) => `${name}`); -export const images = createTable( - "images", +export const posts = createTable( + "posts", { id: varchar("id", { length: 255 }) .notNull() @@ -43,6 +44,26 @@ export const images = createTable( }, ); +export const votes = createTable("votes", { + id: varchar("id", { length: 255 }) + .notNull() + .primaryKey() + .$defaultFn(() => crypto.randomUUID()), + postId: varchar("post_id", { length: 255 }) + .notNull() + .references(() => posts.id), + up: boolean("up").notNull().default(true), + createdById: varchar("created_by", { length: 255 }) + .notNull() + .references(() => users.id), + createdAt: timestamp("created_at", { withTimezone: true }) + .default(sql`CURRENT_TIMESTAMP`) + .notNull(), + updatedAt: timestamp("updated_at", { withTimezone: true }).$onUpdate( + () => new Date(), + ), +}); + export const users = createTable("users", { id: varchar("id", { length: 255 }) .notNull() @@ -60,6 +81,8 @@ export const users = createTable("users", { export const usersRelations = relations(users, ({ many }) => ({ accounts: many(accounts), + posts: many(posts), + votes: many(votes), })); export const accounts = createTable(