DB things

This commit is contained in:
Daniel Flanagan 2022-09-27 15:49:41 -05:00
parent 3d33e72f42
commit 0fc6b1b8a8
Signed by untrusted user: lytedev-divvy
GPG Key ID: 6D69CEEE4ABBCD82
5 changed files with 93 additions and 5 deletions

13
db-migrations.ts Normal file
View File

@ -0,0 +1,13 @@
import { query } from "./db.ts";
await query(`
create extension if not exists "uuid-ossp";
drop table if exists notes;
create table if not exists notes (
id uuid primary key default uuid_generate_v4(),
content text not null,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
`);

25
db.ts Normal file
View File

@ -0,0 +1,25 @@
import * as postgres from "https://deno.land/x/postgres@v0.16.1/mod.ts";
import { type QueryArguments } from "https://deno.land/x/postgres@v0.16.1/query/query.ts?s=QueryArguments";
export { type QueryObjectResult } from "https://deno.land/x/postgres@v0.16.1/query/query.ts?s=QueryArguments";
const databaseUrl = Deno.env.get("DATABASE_URL") ||
"postgresql://danielflanagan:@127.0.0.1:5432/lyricscreen";
const pool = new postgres.Pool(databaseUrl, 3, true);
export async function query(sql: string, ...args: QueryArguments[]) {
let result = null;
try {
const connection = await pool.connect();
try {
result = await connection.queryObject(sql, ...args);
} catch (err) {
console.error("Error querying database:", err);
} finally {
connection.release();
}
} catch (err) {
console.error("Error connecting to database:", err);
}
return result;
}

View File

@ -13,8 +13,9 @@ import * as $6 from "./routes/api/random-uuid.ts";
import * as $7 from "./routes/countdown.tsx";
import * as $8 from "./routes/github/[username].tsx";
import * as $9 from "./routes/index.tsx";
import * as $10 from "./routes/route-config-example.tsx";
import * as $11 from "./routes/search.tsx";
import * as $10 from "./routes/note.tsx";
import * as $11 from "./routes/route-config-example.tsx";
import * as $12 from "./routes/search.tsx";
import * as $$0 from "./islands/Countdown.tsx";
import * as $$1 from "./islands/Counter.tsx";
@ -30,8 +31,9 @@ const manifest = {
"./routes/countdown.tsx": $7,
"./routes/github/[username].tsx": $8,
"./routes/index.tsx": $9,
"./routes/route-config-example.tsx": $10,
"./routes/search.tsx": $11,
"./routes/note.tsx": $10,
"./routes/route-config-example.tsx": $11,
"./routes/search.tsx": $12,
},
islands: {
"./islands/Countdown.tsx": $$0,

View File

@ -10,6 +10,6 @@ export async function handler(
) {
ctx.state.data = "myData";
const resp = await ctx.next();
resp.headers.set("server", "fresh server");
if (resp) resp.headers.set("server", "fresh server");
return resp;
}

48
routes/note.tsx Normal file
View File

@ -0,0 +1,48 @@
import { Handlers, PageProps } from "$fresh/server.ts";
import { query, type QueryObjectResult } from "../db.ts";
interface Note {
id: string;
created_at: Date;
content: string;
}
export const handler: Handlers<Note[] | null> = {
async GET(request, context) {
console.debug({ request, context });
const result = await query("select * from notes");
if (result == null) throw "unable to fetch from database";
const notes = result.rows;
console.debug(notes);
return await context.render(notes);
},
async POST(request, context) {
console.debug({ request, context });
if (request.headers.get("content-type") != "application/json") {
throw "content-type must be application/json";
}
const body = await request.json();
console.log({ body });
if (!("content" in body)) {
throw "no content field present in body";
}
const result = await query(
"insert into notes (content) values ($1) returning id",
body.content,
);
if (result == null) throw "failed to fetch notes";
const { rows: [{ id }] } = result as QueryObjectResult<Note>;
console.debug(id);
},
};
export default function Page({ data }: PageProps<Note[] | null>) {
return (
<div>
<p>Yo!</p>
<pre>
{JSON.stringify(data, null, 2)}
</pre>
</div>
);
}