remove all drops from sql files, add triggers and functions for updated_at, added files and folder tables, update some types
This commit is contained in:
parent
6fdc82dd49
commit
94ba46cc2d
11 changed files with 295 additions and 101 deletions
85
config/sql/files.ts
Normal file
85
config/sql/files.ts
Normal file
|
@ -0,0 +1,85 @@
|
|||
import { logger } from "@helpers/logger";
|
||||
import { type ReservedSQL, sql } from "bun";
|
||||
|
||||
export const order: number = 5;
|
||||
|
||||
export async function createTable(reservation?: ReservedSQL): Promise<void> {
|
||||
let selfReservation: boolean = false;
|
||||
|
||||
if (!reservation) {
|
||||
reservation = await sql.reserve();
|
||||
selfReservation = true;
|
||||
}
|
||||
|
||||
try {
|
||||
await reservation`
|
||||
CREATE TABLE IF NOT EXISTS files (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
owner UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
folder UUID DEFAULT NULL REFERENCES folders(id) ON DELETE SET NULL,
|
||||
|
||||
name VARCHAR(255) NOT NULL,
|
||||
original_name VARCHAR(255),
|
||||
mime_type VARCHAR(255) NOT NULL,
|
||||
size BIGINT NOT NULL,
|
||||
|
||||
views INTEGER DEFAULT 0,
|
||||
max_views INTEGER DEFAULT 1,
|
||||
password TEXT DEFAULT NULL,
|
||||
favorite BOOLEAN DEFAULT FALSE,
|
||||
tags TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
thumbnail BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
|
||||
expires_at TIMESTAMPTZ DEFAULT NULL
|
||||
);
|
||||
`;
|
||||
|
||||
const functionExists: { exists: boolean }[] = await reservation`
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM pg_proc
|
||||
JOIN pg_namespace ON pg_proc.pronamespace = pg_namespace.oid
|
||||
WHERE proname = 'update_files_updated_at' AND nspname = 'public'
|
||||
);
|
||||
`;
|
||||
|
||||
if (!functionExists[0].exists) {
|
||||
await reservation`
|
||||
CREATE FUNCTION update_files_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
`;
|
||||
}
|
||||
|
||||
const triggerExists: { exists: boolean }[] = await reservation`
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM pg_trigger
|
||||
WHERE tgname = 'trigger_update_files_updated_at'
|
||||
);
|
||||
`;
|
||||
|
||||
if (!triggerExists[0].exists) {
|
||||
await reservation`
|
||||
CREATE TRIGGER trigger_update_files_updated_at
|
||||
BEFORE UPDATE ON files
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_files_updated_at();
|
||||
`;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error([
|
||||
"Could not create the files table or trigger:",
|
||||
error as Error,
|
||||
]);
|
||||
throw error;
|
||||
} finally {
|
||||
if (selfReservation) {
|
||||
reservation.release();
|
||||
}
|
||||
}
|
||||
}
|
75
config/sql/folders.ts
Normal file
75
config/sql/folders.ts
Normal file
|
@ -0,0 +1,75 @@
|
|||
import { logger } from "@helpers/logger";
|
||||
import { type ReservedSQL, sql } from "bun";
|
||||
|
||||
export const order: number = 4;
|
||||
|
||||
export async function createTable(reservation?: ReservedSQL): Promise<void> {
|
||||
let selfReservation: boolean = false;
|
||||
|
||||
if (!reservation) {
|
||||
reservation = await sql.reserve();
|
||||
selfReservation = true;
|
||||
}
|
||||
|
||||
try {
|
||||
await reservation`
|
||||
CREATE TABLE IF NOT EXISTS folders (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
owner UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
|
||||
name VARCHAR(255) NOT NULL,
|
||||
public BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
allow_uploads BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
|
||||
);
|
||||
`;
|
||||
|
||||
const functionExists: { exists: boolean }[] = await reservation`
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM pg_proc
|
||||
JOIN pg_namespace ON pg_proc.pronamespace = pg_namespace.oid
|
||||
WHERE proname = 'update_folders_updated_at' AND nspname = 'public'
|
||||
);
|
||||
`;
|
||||
|
||||
if (!functionExists[0].exists) {
|
||||
await reservation`
|
||||
CREATE FUNCTION update_folders_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
`;
|
||||
}
|
||||
|
||||
const triggerExists: { exists: boolean }[] = await reservation`
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM pg_trigger
|
||||
WHERE tgname = 'trigger_update_folders_updated_at'
|
||||
);
|
||||
`;
|
||||
|
||||
if (!triggerExists[0].exists) {
|
||||
await reservation`
|
||||
CREATE TRIGGER trigger_update_folders_updated_at
|
||||
BEFORE UPDATE ON folders
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_folders_updated_at();
|
||||
`;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error([
|
||||
"Could not create the folders table or trigger:",
|
||||
error as Error,
|
||||
]);
|
||||
throw error;
|
||||
} finally {
|
||||
if (selfReservation) {
|
||||
reservation.release();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import { logger } from "@helpers/logger";
|
||||
import { type ReservedSQL, sql } from "bun";
|
||||
|
||||
export const order: number = 3;
|
||||
|
||||
export async function createTable(reservation?: ReservedSQL): Promise<void> {
|
||||
let selfReservation: boolean = false;
|
||||
|
||||
|
@ -29,26 +31,3 @@ export async function createTable(reservation?: ReservedSQL): Promise<void> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function drop(
|
||||
cascade: boolean,
|
||||
reservation?: ReservedSQL,
|
||||
): Promise<void> {
|
||||
let selfReservation: boolean = false;
|
||||
|
||||
if (!reservation) {
|
||||
reservation = await sql.reserve();
|
||||
selfReservation = true;
|
||||
}
|
||||
|
||||
try {
|
||||
await reservation`DROP TABLE IF EXISTS invites ${cascade ? "CASCADE" : ""};`;
|
||||
} catch (error) {
|
||||
logger.error(["Could not drop the invites table:", error as Error]);
|
||||
throw error;
|
||||
} finally {
|
||||
if (selfReservation) {
|
||||
reservation.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { logger } from "@helpers/logger";
|
||||
import { type ReservedSQL, sql } from "bun";
|
||||
|
||||
export const order: number = 2;
|
||||
|
||||
const defaultSettings: Setting[] = [
|
||||
{ key: "default_role", value: "user" },
|
||||
{ key: "default_timezone", value: "UTC" },
|
||||
|
@ -21,45 +23,62 @@ export async function createTable(reservation?: ReservedSQL): Promise<void> {
|
|||
|
||||
try {
|
||||
await reservation`
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
"key" VARCHAR(64) PRIMARY KEY NOT NULL UNIQUE,
|
||||
"value" TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
|
||||
);`;
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
"key" VARCHAR(64) PRIMARY KEY NOT NULL UNIQUE,
|
||||
"value" TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
|
||||
);
|
||||
`;
|
||||
|
||||
const functionExists: { exists: boolean }[] = await reservation`
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM pg_proc
|
||||
JOIN pg_namespace ON pg_proc.pronamespace = pg_namespace.oid
|
||||
WHERE proname = 'update_settings_updated_at' AND nspname = 'public'
|
||||
);
|
||||
`;
|
||||
|
||||
if (!functionExists[0].exists) {
|
||||
await reservation`
|
||||
CREATE FUNCTION update_settings_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
`;
|
||||
}
|
||||
|
||||
const triggerExists: { exists: boolean }[] = await reservation`
|
||||
SELECT EXISTS (
|
||||
SELECT 1 FROM pg_trigger
|
||||
WHERE tgname = 'trigger_update_settings_updated_at'
|
||||
);
|
||||
`;
|
||||
|
||||
if (!triggerExists[0].exists) {
|
||||
await reservation`
|
||||
CREATE TRIGGER trigger_update_settings_updated_at
|
||||
BEFORE UPDATE ON settings
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_settings_updated_at();
|
||||
`;
|
||||
}
|
||||
|
||||
for (const setting of defaultSettings) {
|
||||
await reservation`
|
||||
INSERT INTO settings ("key", "value")
|
||||
VALUES (${setting.key}, ${setting.value})
|
||||
ON CONFLICT ("key")
|
||||
DO NOTHING;`;
|
||||
INSERT INTO settings ("key", "value")
|
||||
VALUES (${setting.key}, ${setting.value})
|
||||
ON CONFLICT ("key") DO NOTHING;
|
||||
`;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(["Could not create the settings table:", error as Error]);
|
||||
throw error;
|
||||
} finally {
|
||||
if (selfReservation) {
|
||||
reservation.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function drop(
|
||||
cascade: boolean,
|
||||
reservation?: ReservedSQL,
|
||||
): Promise<void> {
|
||||
let selfReservation: boolean = false;
|
||||
|
||||
if (!reservation) {
|
||||
reservation = await sql.reserve();
|
||||
selfReservation = true;
|
||||
}
|
||||
|
||||
try {
|
||||
await reservation`DROP TABLE IF EXISTS settings ${cascade ? "CASCADE" : ""};`;
|
||||
} catch (error) {
|
||||
logger.error(["Could not drop the settings table:", error as Error]);
|
||||
logger.error([
|
||||
"Could not create the settings table or trigger:",
|
||||
error as Error,
|
||||
]);
|
||||
throw error;
|
||||
} finally {
|
||||
if (selfReservation) {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { logger } from "@helpers/logger";
|
||||
import { type ReservedSQL, sql } from "bun";
|
||||
|
||||
export const order: number = 1;
|
||||
|
||||
export async function createTable(reservation?: ReservedSQL): Promise<void> {
|
||||
let selfReservation: boolean = false;
|
||||
|
||||
|
@ -11,20 +13,20 @@ export async function createTable(reservation?: ReservedSQL): Promise<void> {
|
|||
|
||||
try {
|
||||
await reservation`
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
authorization_token UUID NOT NULL UNIQUE DEFAULT gen_random_uuid(),
|
||||
username VARCHAR(20) NOT NULL UNIQUE,
|
||||
email VARCHAR(254) NOT NULL UNIQUE,
|
||||
email_verified boolean NOT NULL DEFAULT false,
|
||||
password TEXT NOT NULL,
|
||||
avatar boolean NOT NULL DEFAULT false,
|
||||
roles TEXT[] NOT NULL DEFAULT ARRAY['user'],
|
||||
timezone VARCHAR(64) DEFAULT NULL,
|
||||
invited_by UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
|
||||
last_seen TIMESTAMPTZ DEFAULT NOW() NOT NULL
|
||||
);`;
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
authorization_token UUID NOT NULL UNIQUE DEFAULT gen_random_uuid(),
|
||||
username VARCHAR(20) NOT NULL UNIQUE,
|
||||
email VARCHAR(254) NOT NULL UNIQUE,
|
||||
email_verified boolean NOT NULL DEFAULT false,
|
||||
password TEXT NOT NULL,
|
||||
avatar boolean NOT NULL DEFAULT false,
|
||||
roles TEXT[] NOT NULL DEFAULT ARRAY['user'],
|
||||
timezone VARCHAR(64) DEFAULT NULL,
|
||||
invited_by UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
|
||||
last_seen TIMESTAMPTZ DEFAULT NOW() NOT NULL
|
||||
);`;
|
||||
} catch (error) {
|
||||
logger.error(["Could not create the users table:", error as Error]);
|
||||
throw error;
|
||||
|
@ -35,29 +37,6 @@ export async function createTable(reservation?: ReservedSQL): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
export async function drop(
|
||||
cascade: boolean,
|
||||
reservation?: ReservedSQL,
|
||||
): Promise<void> {
|
||||
let selfReservation: boolean = false;
|
||||
|
||||
if (!reservation) {
|
||||
reservation = await sql.reserve();
|
||||
selfReservation = true;
|
||||
}
|
||||
|
||||
try {
|
||||
await reservation`DROP TABLE IF EXISTS users ${cascade ? "CASCADE" : ""};`;
|
||||
} catch (error) {
|
||||
logger.error(["Could not drop the users table:", error as Error]);
|
||||
throw error;
|
||||
} finally {
|
||||
if (selfReservation) {
|
||||
reservation.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// * Validation functions
|
||||
|
||||
// ? should support non english characters but wont mess up the url
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue