This commit is contained in:
2026-08-22 02:59:16 +02:00
commit 6a5bb1d699
100 changed files with 17409 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
CREATE TABLE IF NOT EXISTS gifts (
id TEXT PRIMARY KEY NOT NULL,
slug TEXT NOT NULL UNIQUE,
recipient_name TEXT NOT NULL,
sender_name TEXT NOT NULL,
title TEXT NOT NULL,
intro_message TEXT NOT NULL,
reveal_message TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'published',
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT gifts_status_check CHECK (status IN ('draft', 'published', 'archived'))
);
CREATE TABLE IF NOT EXISTS gift_items (
id TEXT PRIMARY KEY NOT NULL,
gift_id TEXT NOT NULL REFERENCES gifts(id) ON DELETE CASCADE,
type TEXT NOT NULL,
title TEXT,
text TEXT,
media_url TEXT,
sort_order INTEGER NOT NULL DEFAULT 0,
metadata TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT gift_items_type_check CHECK (length(trim(type)) > 0)
);
CREATE INDEX IF NOT EXISTS gift_items_gift_id_sort_order_idx
ON gift_items (gift_id, sort_order, id);
+91
View File
@@ -0,0 +1,91 @@
INSERT INTO gifts (
id,
slug,
recipient_name,
sender_name,
title,
intro_message,
reveal_message,
status
)
VALUES (
'11111111-1111-4111-8111-111111111111',
'demo',
'Anna',
'Alex',
'A little surprise for you',
'I made something for you.',
'You make ordinary days feel like something worth remembering. Here is to all the little adventures still ahead.',
'published'
)
ON CONFLICT (slug) DO UPDATE SET
recipient_name = excluded.recipient_name,
sender_name = excluded.sender_name,
title = excluded.title,
intro_message = excluded.intro_message,
reveal_message = excluded.reveal_message,
status = excluded.status,
updated_at = CURRENT_TIMESTAMP;
INSERT INTO gift_items (id, gift_id, type, title, text, media_url, sort_order, metadata)
SELECT
'22222222-2222-4222-8222-222222222222',
id,
'image',
'The good kind of ordinary.',
'The tiny moments are usually the ones that stay with us the longest.',
'https://images.unsplash.com/photo-1511988617509-8e73b0f3b7d2?auto=format&fit=crop&w=1400&q=85',
1,
'{"caption":"A little snapshot of a very good day.","accent":"coral"}'
FROM gifts
WHERE slug = 'demo'
ON CONFLICT (id) DO UPDATE SET
gift_id = excluded.gift_id,
type = excluded.type,
title = excluded.title,
text = excluded.text,
media_url = excluded.media_url,
sort_order = excluded.sort_order,
metadata = excluded.metadata;
INSERT INTO gift_items (id, gift_id, type, title, text, media_url, sort_order, metadata)
SELECT
'33333333-3333-4333-8333-333333333333',
id,
'text',
'A note for your next chapter.',
'Keep choosing the places, people, and tiny rituals that make you feel most like yourself. I will always be cheering for you.',
NULL,
2,
'{"eyebrow":"A note from me","accent":"lavender"}'
FROM gifts
WHERE slug = 'demo'
ON CONFLICT (id) DO UPDATE SET
gift_id = excluded.gift_id,
type = excluded.type,
title = excluded.title,
text = excluded.text,
media_url = excluded.media_url,
sort_order = excluded.sort_order,
metadata = excluded.metadata;
INSERT INTO gift_items (id, gift_id, type, title, text, media_url, sort_order, metadata)
SELECT
'44444444-4444-4444-8444-444444444444',
id,
'text',
'One more thing.',
'There is nowhere else I would rather be than somewhere in the middle of the next story with you.',
NULL,
3,
'{"eyebrow":"P.S.","accent":"gold"}'
FROM gifts
WHERE slug = 'demo'
ON CONFLICT (id) DO UPDATE SET
gift_id = excluded.gift_id,
type = excluded.type,
title = excluded.title,
text = excluded.text,
media_url = excluded.media_url,
sort_order = excluded.sort_order,
metadata = excluded.metadata;
@@ -0,0 +1,92 @@
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY NOT NULL,
email TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
name TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE UNIQUE INDEX IF NOT EXISTS users_email_lower_idx ON users (lower(email));
CREATE TABLE IF NOT EXISTS galleries (
id TEXT PRIMARY KEY NOT NULL,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
slug TEXT NOT NULL UNIQUE,
title TEXT NOT NULL,
client_name TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'draft',
password_hash TEXT,
downloads_enabled INTEGER NOT NULL DEFAULT 1,
favorites_enabled INTEGER NOT NULL DEFAULT 1,
download_all_enabled INTEGER NOT NULL DEFAULT 1,
watermark_enabled INTEGER NOT NULL DEFAULT 0,
expires_at TEXT,
cover_media_id TEXT,
theme_config TEXT NOT NULL DEFAULT '{}',
branding_config TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
published_at TEXT,
CONSTRAINT galleries_status_check CHECK (status IN ('draft', 'published', 'archived'))
);
CREATE INDEX IF NOT EXISTS galleries_user_id_created_at_idx ON galleries (user_id, created_at DESC);
CREATE TABLE IF NOT EXISTS media (
id TEXT PRIMARY KEY NOT NULL,
gallery_id TEXT NOT NULL REFERENCES galleries(id) ON DELETE CASCADE,
original_filename TEXT NOT NULL,
mime_type TEXT NOT NULL,
file_size INTEGER NOT NULL DEFAULT 0,
storage_key TEXT NOT NULL,
external_url TEXT,
thumbnail_key TEXT,
preview_key TEXT,
processing_status TEXT NOT NULL DEFAULT 'UPLOADING',
processing_error TEXT,
width INTEGER,
height INTEGER,
duration_seconds REAL,
sort_order INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT media_processing_status_check CHECK (processing_status IN ('UPLOADING', 'PROCESSING', 'READY', 'FAILED'))
);
CREATE INDEX IF NOT EXISTS media_gallery_sort_order_idx ON media (gallery_id, sort_order, id);
CREATE TABLE IF NOT EXISTS favorites (
id TEXT PRIMARY KEY NOT NULL,
gallery_id TEXT NOT NULL REFERENCES galleries(id) ON DELETE CASCADE,
media_id TEXT NOT NULL REFERENCES media(id) ON DELETE CASCADE,
visitor_id TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE (gallery_id, media_id, visitor_id)
);
CREATE TABLE IF NOT EXISTS downloads (
id TEXT PRIMARY KEY NOT NULL,
gallery_id TEXT NOT NULL REFERENCES galleries(id) ON DELETE CASCADE,
media_id TEXT REFERENCES media(id) ON DELETE SET NULL,
visitor_id TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS downloads_gallery_created_at_idx ON downloads (gallery_id, created_at DESC);
CREATE TABLE IF NOT EXISTS download_jobs (
id TEXT PRIMARY KEY NOT NULL,
gallery_id TEXT NOT NULL REFERENCES galleries(id) ON DELETE CASCADE,
visitor_id TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'QUEUED',
storage_key TEXT,
error TEXT,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
completed_at TEXT,
CONSTRAINT download_jobs_status_check CHECK (status IN ('QUEUED', 'PROCESSING', 'READY', 'FAILED'))
);
CREATE INDEX IF NOT EXISTS download_jobs_gallery_visitor_idx ON download_jobs (gallery_id, visitor_id, created_at DESC);