feat: drizzle schema + migrations for products/snapshots/alerts
This commit is contained in:
38
drizzle/0000_motionless_beast.sql
Normal file
38
drizzle/0000_motionless_beast.sql
Normal file
@@ -0,0 +1,38 @@
|
||||
CREATE TABLE "alerts" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"product_id" uuid NOT NULL,
|
||||
"type" text NOT NULL,
|
||||
"config" jsonb NOT NULL,
|
||||
"enabled" boolean DEFAULT true NOT NULL,
|
||||
"last_triggered_at" timestamp with time zone,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "alert_type_check" CHECK ("alerts"."type" in ('target_price','all_time_low','percent_drop'))
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "price_snapshots" (
|
||||
"id" bigserial PRIMARY KEY NOT NULL,
|
||||
"product_id" uuid NOT NULL,
|
||||
"price" numeric(10, 2),
|
||||
"currency" text DEFAULT 'EUR' NOT NULL,
|
||||
"availability" text,
|
||||
"error" text,
|
||||
"scraped_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "products" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"url" text NOT NULL,
|
||||
"shop" text NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"image_url" text,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"enabled" boolean DEFAULT true NOT NULL,
|
||||
"last_scraped_at" timestamp with time zone,
|
||||
"consecutive_failures" integer DEFAULT 0 NOT NULL,
|
||||
CONSTRAINT "products_url_unique" UNIQUE("url"),
|
||||
CONSTRAINT "shop_check" CHECK ("products"."shop" in ('amazon','idealo','geizhals'))
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "alerts" ADD CONSTRAINT "alerts_product_id_products_id_fk" FOREIGN KEY ("product_id") REFERENCES "public"."products"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "price_snapshots" ADD CONSTRAINT "price_snapshots_product_id_products_id_fk" FOREIGN KEY ("product_id") REFERENCES "public"."products"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX "snapshots_product_scraped_idx" ON "price_snapshots" USING btree ("product_id","scraped_at" DESC NULLS LAST);
|
||||
273
drizzle/meta/0000_snapshot.json
Normal file
273
drizzle/meta/0000_snapshot.json
Normal file
@@ -0,0 +1,273 @@
|
||||
{
|
||||
"id": "17d857bc-1a3e-4c61-80cc-1d863410f24a",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"public.alerts": {
|
||||
"name": "alerts",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"product_id": {
|
||||
"name": "product_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"config": {
|
||||
"name": "config",
|
||||
"type": "jsonb",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"enabled": {
|
||||
"name": "enabled",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": true
|
||||
},
|
||||
"last_triggered_at": {
|
||||
"name": "last_triggered_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"alerts_product_id_products_id_fk": {
|
||||
"name": "alerts_product_id_products_id_fk",
|
||||
"tableFrom": "alerts",
|
||||
"tableTo": "products",
|
||||
"columnsFrom": [
|
||||
"product_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"alert_type_check": {
|
||||
"name": "alert_type_check",
|
||||
"value": "\"alerts\".\"type\" in ('target_price','all_time_low','percent_drop')"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.price_snapshots": {
|
||||
"name": "price_snapshots",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "bigserial",
|
||||
"primaryKey": true,
|
||||
"notNull": true
|
||||
},
|
||||
"product_id": {
|
||||
"name": "product_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"price": {
|
||||
"name": "price",
|
||||
"type": "numeric(10, 2)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"currency": {
|
||||
"name": "currency",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'EUR'"
|
||||
},
|
||||
"availability": {
|
||||
"name": "availability",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"error": {
|
||||
"name": "error",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"scraped_at": {
|
||||
"name": "scraped_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"snapshots_product_scraped_idx": {
|
||||
"name": "snapshots_product_scraped_idx",
|
||||
"columns": [
|
||||
{
|
||||
"expression": "product_id",
|
||||
"isExpression": false,
|
||||
"asc": true,
|
||||
"nulls": "last"
|
||||
},
|
||||
{
|
||||
"expression": "scraped_at",
|
||||
"isExpression": false,
|
||||
"asc": false,
|
||||
"nulls": "last"
|
||||
}
|
||||
],
|
||||
"isUnique": false,
|
||||
"concurrently": false,
|
||||
"method": "btree",
|
||||
"with": {}
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"price_snapshots_product_id_products_id_fk": {
|
||||
"name": "price_snapshots_product_id_products_id_fk",
|
||||
"tableFrom": "price_snapshots",
|
||||
"tableTo": "products",
|
||||
"columnsFrom": [
|
||||
"product_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.products": {
|
||||
"name": "products",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"url": {
|
||||
"name": "url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"shop": {
|
||||
"name": "shop",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"image_url": {
|
||||
"name": "image_url",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"enabled": {
|
||||
"name": "enabled",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": true
|
||||
},
|
||||
"last_scraped_at": {
|
||||
"name": "last_scraped_at",
|
||||
"type": "timestamp with time zone",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"consecutive_failures": {
|
||||
"name": "consecutive_failures",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"products_url_unique": {
|
||||
"name": "products_url_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"url"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {
|
||||
"shop_check": {
|
||||
"name": "shop_check",
|
||||
"value": "\"products\".\"shop\" in ('amazon','idealo','geizhals')"
|
||||
}
|
||||
},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {},
|
||||
"schemas": {},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
13
drizzle/meta/_journal.json
Normal file
13
drizzle/meta/_journal.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "7",
|
||||
"when": 1779716926721,
|
||||
"tag": "0000_motionless_beast",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user