Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"@scalar/fastify-api-reference": "^1.38.1",
"@sinclair/typebox": "catalog:",
"bullmq": "catalog:",
"drizzle-orm": "catalog:",
"fastify": "^5.6.0",
"fastify-plugin": "^5.0.1"
},
Expand Down
3 changes: 1 addition & 2 deletions apps/api/src/routes/tasks/post-images.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { FastifyPluginAsync } from "fastify";
import { eq } from "drizzle-orm";
import { type PostImageOutput, Tasks, env } from "@playfulprogramming/common";
import { db } from "@playfulprogramming/db";
import { Type, type Static } from "@sinclair/typebox";
Expand Down Expand Up @@ -88,7 +87,7 @@ const postImagesRoutes: FastifyPluginAsync = async (fastify) => {
},
async (request, reply) => {
const result = await db.query.postImages.findFirst({
where: (postImages) => eq(postImages.slug, request.body.slug),
where: { slug: request.body.slug },
});

let shouldSubmitJob = false;
Expand Down
3 changes: 1 addition & 2 deletions apps/api/src/routes/tasks/url-metadata.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { FastifyPluginAsync } from "fastify";
import { eq } from "drizzle-orm";
import {
type UrlMetadataInput,
type UrlMetadataOutput,
Expand Down Expand Up @@ -109,7 +108,7 @@ const urlMetadataRoutes: FastifyPluginAsync = async (fastify) => {
).toString();

const result = await db.query.urlMetadata.findFirst({
where: (metadata) => eq(metadata.url, normalizedUrl),
where: { url: normalizedUrl },
});

let shouldSubmitJob = false;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"engines": {
"node": ">=22.6.0"
},
"packageManager": "pnpm@10.6.1",
"packageManager": "pnpm@10.28.2",
"devDependencies": {
"@eslint/js": "^9.37.0",
"@types/node": "^24.3.1",
Expand Down
5 changes: 0 additions & 5 deletions packages/db/drizzle/0001_broad_archangel.sql

This file was deleted.

7 changes: 0 additions & 7 deletions packages/db/drizzle/0003_famous_silver_samurai.sql

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
CREATE TABLE "post_images" (
CREATE TABLE IF NOT EXISTS "post_images" (
"slug" varchar(2048) PRIMARY KEY NOT NULL,
"banner_key" varchar(2048) NOT NULL,
"link_preview_key" varchar(2048) NOT NULL
);
--> statement-breakpoint
CREATE TABLE "url_metadata" (
CREATE TABLE IF NOT EXISTS "url_metadata" (
"url" varchar(2048) PRIMARY KEY NOT NULL,
"title" varchar(2048),
"icon_key" varchar(2048),
Expand Down
212 changes: 212 additions & 0 deletions packages/db/drizzle/20250619151208_gigantic_epoch/snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
{
"id": "c9e5f7d0-b17b-4966-b2aa-6d9392ba97d6",
"prevIds": [
"00000000-0000-0000-0000-000000000000"
],
"version": "8",
"dialect": "postgres",
"ddl": [
{
"isRlsEnabled": false,
"name": "post_images",
"schema": "public",
"entityType": "tables"
},
{
"columns": [
"slug"
],
"nameExplicit": false,
"name": "post_images_pkey",
"schema": "public",
"table": "post_images",
"entityType": "pks"
},
{
"type": "varchar(2048)",
"typeSchema": null,
"notNull": true,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "slug",
"schema": "public",
"table": "post_images",
"entityType": "columns"
},
{
"type": "varchar(2048)",
"typeSchema": null,
"notNull": true,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "banner_key",
"schema": "public",
"table": "post_images",
"entityType": "columns"
},
{
"type": "varchar(2048)",
"typeSchema": null,
"notNull": true,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "link_preview_key",
"schema": "public",
"table": "post_images",
"entityType": "columns"
},
{
"isRlsEnabled": false,
"name": "url_metadata",
"schema": "public",
"entityType": "tables"
},
{
"columns": [
"url"
],
"nameExplicit": false,
"name": "url_metadata_pkey",
"schema": "public",
"table": "url_metadata",
"entityType": "pks"
},
{
"type": "varchar(2048)",
"typeSchema": null,
"notNull": true,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "url",
"schema": "public",
"table": "url_metadata",
"entityType": "columns"
},
{
"type": "varchar(2048)",
"typeSchema": null,
"notNull": false,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "title",
"schema": "public",
"table": "url_metadata",
"entityType": "columns"
},
{
"type": "varchar(2048)",
"typeSchema": null,
"notNull": false,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "icon_key",
"schema": "public",
"table": "url_metadata",
"entityType": "columns"
},
{
"type": "integer",
"typeSchema": null,
"notNull": false,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "icon_width",
"schema": "public",
"table": "url_metadata",
"entityType": "columns"
},
{
"type": "integer",
"typeSchema": null,
"notNull": false,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "icon_height",
"schema": "public",
"table": "url_metadata",
"entityType": "columns"
},
{
"type": "varchar(2048)",
"typeSchema": null,
"notNull": false,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "banner_key",
"schema": "public",
"table": "url_metadata",
"entityType": "columns"
},
{
"type": "integer",
"typeSchema": null,
"notNull": false,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "banner_width",
"schema": "public",
"table": "url_metadata",
"entityType": "columns"
},
{
"type": "integer",
"typeSchema": null,
"notNull": false,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "banner_height",
"schema": "public",
"table": "url_metadata",
"entityType": "columns"
},
{
"type": "timestamp with time zone",
"typeSchema": null,
"notNull": true,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "fetched_at",
"schema": "public",
"table": "url_metadata",
"entityType": "columns"
},
{
"type": "boolean",
"typeSchema": null,
"notNull": true,
"dimensions": 0,
"default": null,
"generated": null,
"identity": null,
"name": "error",
"schema": "public",
"table": "url_metadata",
"entityType": "columns"
}
],
"renames": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER TABLE "post_images" ALTER COLUMN "banner_key" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "post_images" ALTER COLUMN "link_preview_key" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "post_images" ADD COLUMN IF NOT EXISTS "index_md5" varchar(2048);--> statement-breakpoint
ALTER TABLE "post_images" ADD COLUMN IF NOT EXISTS "fetched_at" timestamp with time zone NOT NULL;--> statement-breakpoint
ALTER TABLE "post_images" ADD COLUMN IF NOT EXISTS "error" boolean NOT NULL;
Comment on lines +4 to +5
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Adding NOT NULL columns without a DEFAULT will fail on non-empty tables.

If post_images already contains rows, PostgreSQL will reject these ALTER TABLE … ADD COLUMN statements because it cannot assign a value to existing rows for a NOT NULL column that has no default. The IF NOT EXISTS guard only prevents adding a duplicate column — it does not help here.

A typical fix is to either:

  1. Add the columns as nullable first, backfill, then set NOT NULL, or
  2. Provide a sensible DEFAULT (e.g., DEFAULT now() for fetched_at, DEFAULT false for error).
🐛 Proposed fix — add defaults
-ALTER TABLE "post_images" ADD COLUMN IF NOT EXISTS "fetched_at" timestamp with time zone NOT NULL;--> statement-breakpoint
-ALTER TABLE "post_images" ADD COLUMN IF NOT EXISTS "error" boolean NOT NULL;
+ALTER TABLE "post_images" ADD COLUMN IF NOT EXISTS "fetched_at" timestamp with time zone NOT NULL DEFAULT now();--> statement-breakpoint
+ALTER TABLE "post_images" ADD COLUMN IF NOT EXISTS "error" boolean NOT NULL DEFAULT false;

If these defaults should not persist on future inserts, you can drop them after the migration:

ALTER TABLE "post_images" ALTER COLUMN "fetched_at" DROP DEFAULT;
ALTER TABLE "post_images" ALTER COLUMN "error" DROP DEFAULT;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ALTER TABLE "post_images" ADD COLUMN IF NOT EXISTS "fetched_at" timestamp with time zone NOT NULL;--> statement-breakpoint
ALTER TABLE "post_images" ADD COLUMN IF NOT EXISTS "error" boolean NOT NULL;
ALTER TABLE "post_images" ADD COLUMN IF NOT EXISTS "fetched_at" timestamp with time zone NOT NULL DEFAULT now();--> statement-breakpoint
ALTER TABLE "post_images" ADD COLUMN IF NOT EXISTS "error" boolean NOT NULL DEFAULT false;
🤖 Prompt for AI Agents
In `@packages/db/drizzle/20250719232913_broad_archangel/migration.sql` around
lines 4 - 5, The ALTER TABLE statements on "post_images" add NOT NULL columns
"fetched_at" and "error" without defaults which will fail on non-empty tables;
fix by either (A) add them as nullable, backfill existing rows, then ALTER to
SET NOT NULL (use "fetched_at" and "error" names for backfill/update and then
set NOT NULL), or (B) add them with sensible DEFAULTs (e.g., DEFAULT now() for
"fetched_at" and DEFAULT false for "error") and then optionally DROP DEFAULTs
after the migration; implement one of these approaches for the ALTER TABLE
changes referencing "post_images", "fetched_at", and "error".

Loading