Sternboard: free retro board, no signup (initial)
Servidor Fastify + Socket.IO + Drizzle/Postgres; front Vite+React (EN/ES, tema claro/oscuro). Tableros por columnas con plantillas, notas privadas/públicas, agrupación, votos configurables (multivoto), timer compartido con alarma, fases, action items, export Markdown/JSON e import, autodestrucción, gestión de columnas. Imagen única (front servido por el servidor) y CI que la construye y publica.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import postgres from "postgres";
|
||||
|
||||
// Crea la base de datos e2e y su esquema desde cero antes de arrancar los servidores.
|
||||
const DDL = `
|
||||
DROP TABLE IF EXISTS action_items, votes, notes, groups, columns, boards CASCADE;
|
||||
CREATE TABLE boards (
|
||||
id text PRIMARY KEY, title text NOT NULL, phase text NOT NULL DEFAULT 'writing',
|
||||
revealed boolean NOT NULL DEFAULT false, votes_revealed boolean NOT NULL DEFAULT false,
|
||||
votes_per_user integer NOT NULL DEFAULT 3, allow_multi_vote boolean NOT NULL DEFAULT true,
|
||||
moderation_mode text NOT NULL DEFAULT 'everyone', show_card_creators boolean NOT NULL DEFAULT true,
|
||||
locked boolean NOT NULL DEFAULT false,
|
||||
timer_ends_at timestamptz, timer_running boolean NOT NULL DEFAULT false,
|
||||
moderator_token text NOT NULL, created_at timestamptz NOT NULL DEFAULT now(), expires_at timestamptz
|
||||
);
|
||||
CREATE TABLE columns (
|
||||
id text PRIMARY KEY, board_id text NOT NULL REFERENCES boards(id) ON DELETE CASCADE,
|
||||
title text NOT NULL, position integer NOT NULL
|
||||
);
|
||||
CREATE TABLE groups (
|
||||
id text PRIMARY KEY, board_id text NOT NULL REFERENCES boards(id) ON DELETE CASCADE,
|
||||
column_id text NOT NULL REFERENCES columns(id) ON DELETE CASCADE,
|
||||
title text NOT NULL DEFAULT '', position double precision NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE TABLE notes (
|
||||
id text PRIMARY KEY, board_id text NOT NULL REFERENCES boards(id) ON DELETE CASCADE,
|
||||
column_id text NOT NULL REFERENCES columns(id) ON DELETE CASCADE,
|
||||
group_id text REFERENCES groups(id) ON DELETE SET NULL,
|
||||
author_id text NOT NULL, author_name text NOT NULL, text text NOT NULL, color text,
|
||||
revealed boolean NOT NULL DEFAULT false, position double precision NOT NULL DEFAULT 0,
|
||||
created_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE TABLE votes (
|
||||
board_id text NOT NULL REFERENCES boards(id) ON DELETE CASCADE,
|
||||
target_type text NOT NULL, target_id text NOT NULL, participant_id text NOT NULL,
|
||||
count integer NOT NULL DEFAULT 1
|
||||
);
|
||||
CREATE UNIQUE INDEX votes_target_participant_uniq ON votes (target_id, participant_id);
|
||||
CREATE TABLE action_items (
|
||||
id text PRIMARY KEY, board_id text NOT NULL REFERENCES boards(id) ON DELETE CASCADE,
|
||||
text text NOT NULL, owner text, done boolean NOT NULL DEFAULT false,
|
||||
created_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
`;
|
||||
|
||||
export default async function globalSetup() {
|
||||
const url = process.env.E2E_DATABASE_URL ?? "postgres://retro:retro@localhost:5433/retro_e2e";
|
||||
const dbName = new URL(url).pathname.slice(1);
|
||||
const admin = postgres(url.replace(`/${dbName}`, "/postgres"), { max: 1 });
|
||||
try {
|
||||
const exists = await admin`SELECT 1 FROM pg_database WHERE datname = ${dbName}`;
|
||||
if (exists.length === 0) await admin.unsafe(`CREATE DATABASE ${dbName}`);
|
||||
} finally {
|
||||
await admin.end();
|
||||
}
|
||||
const sql = postgres(url, { max: 1 });
|
||||
try {
|
||||
await sql.unsafe(DDL);
|
||||
} finally {
|
||||
await sql.end();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user