in progress: build out server side
This commit is contained in:
34
server/actions/project.actions.ts
Normal file
34
server/actions/project.actions.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { Project, isProject } from "../entities/project";
|
||||
import { Client } from "pg";
|
||||
import createClient from "../services/pg";
|
||||
|
||||
export default class ProjectRepository {
|
||||
async getProjects() {
|
||||
'use server';
|
||||
|
||||
const client = createClient();
|
||||
|
||||
const { rows } = await client.query("SELECT * FROM projects");
|
||||
await client.end();
|
||||
|
||||
if (rows.every(row => isProject(row))) {
|
||||
return rows as Project[];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async getProjectById(id: string) {
|
||||
'use server';
|
||||
|
||||
const client = createClient();
|
||||
const { rows } = await client.query("SELECT * FROM projects WHERE id = $1", [id]);
|
||||
await client.end();
|
||||
|
||||
if (rows.every(row => isProject(row))) {
|
||||
return rows[0] as Project;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import supabaseClient from "../services/supabase";
|
||||
|
||||
export default class ProjectsActions {
|
||||
static api = supabaseClient();
|
||||
|
||||
static async getProjects() {
|
||||
const { data, error } = await this.api.from("projects").select("*");
|
||||
|
||||
if (error) throw error;
|
||||
return data;
|
||||
}
|
||||
|
||||
static async getProjectsById(id: string) {
|
||||
const { data, error } = await this.api.from("projects").select("*").eq("id", id);
|
||||
|
||||
if (error) throw error;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,15 @@
|
||||
'use server';
|
||||
|
||||
import supabaseClient from "../services/supabase";
|
||||
|
||||
export default class WorkActions {
|
||||
static api = supabaseClient();
|
||||
// static async getWork() {
|
||||
// const { data, error } = await this.api.from("work").select("*");
|
||||
|
||||
static async getWork() {
|
||||
const { data, error } = await this.api.from("work").select("*");
|
||||
// if (error) throw error;
|
||||
// return data;
|
||||
// }
|
||||
|
||||
if (error) throw error;
|
||||
return data;
|
||||
}
|
||||
// static async getWorkById(id: string) {
|
||||
// const { data, error } = await this.api.from("work").select("*").eq("id", id);
|
||||
|
||||
static async getWorkById(id: string) {
|
||||
const { data, error } = await this.api.from("work").select("*").eq("id", id);
|
||||
|
||||
if (error) throw error;
|
||||
return data;
|
||||
}
|
||||
// if (error) throw error;
|
||||
// return data;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,9 +1,48 @@
|
||||
type Project = {
|
||||
name: string;
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
current: boolean;
|
||||
description: string;
|
||||
tagIDs: string[];
|
||||
media?: string[]; // array of URLs
|
||||
import { z } from "zod";
|
||||
|
||||
export type Project = {
|
||||
name: string;
|
||||
description: string;
|
||||
startDate: Date;
|
||||
endDate?: Date;
|
||||
tagIDs?: string[];
|
||||
media?: string[]; // array of URLs
|
||||
}
|
||||
|
||||
export class ProjectCreationError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = "ProjectCreationError";
|
||||
}
|
||||
}
|
||||
|
||||
export const ZProject = z.object({
|
||||
name: z.string(),
|
||||
description: z.string(),
|
||||
startDate: z.date(),
|
||||
endDate: z.date().optional(),
|
||||
tagIDs: z.array(z.string()).optional(),
|
||||
media: z.array(z.string()).optional(),
|
||||
})
|
||||
|
||||
export function createProject(data: Partial<Project>) {
|
||||
if (!data.name) throw new ProjectCreationError("Project name is required");
|
||||
if (!data.description) throw new ProjectCreationError("Project description is required");
|
||||
|
||||
const today = new Date();
|
||||
|
||||
const completeInput = {
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
startDate: data.startDate || today,
|
||||
}
|
||||
|
||||
const parsedProject = ZProject.safeParse(completeInput);
|
||||
|
||||
if (!parsedProject.success) throw new ProjectCreationError("Invalid project data");
|
||||
return parsedProject.data satisfies Project;
|
||||
}
|
||||
|
||||
export function isProject(data: unknown): data is Project {
|
||||
return ZProject.safeParse(data).success;
|
||||
}
|
||||
|
||||
19
server/services/pg.ts
Normal file
19
server/services/pg.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Client } from "pg";
|
||||
|
||||
export class PostgresError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = "PostgresError";
|
||||
}
|
||||
}
|
||||
|
||||
export default function createClient() {
|
||||
if (!process.env.POSTGRES_URL) {
|
||||
throw new PostgresError("Database connection configured incorrectly")
|
||||
}
|
||||
|
||||
return new Client({
|
||||
connectionString: process.env.POSTGRES_URL
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { createClient } from "@supabase/supabase-js";
|
||||
|
||||
export default function supabaseClient() {
|
||||
if (typeof process.env.SUPABASE_URL !== "string") {
|
||||
throw new Error("SUPABASE_URL is not defined");
|
||||
}
|
||||
|
||||
if (typeof process.env.SUPABASE_KEY !== "string") {
|
||||
throw new Error("SUPABASE_KEY is not defined");
|
||||
}
|
||||
|
||||
return createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY);
|
||||
}
|
||||
Reference in New Issue
Block a user