From c97c3f7b6978cc4d7128b6e0efe4c3d045b3fee3 Mon Sep 17 00:00:00 2001
From: Daniel Flanagan
Date: Sat, 8 Oct 2022 02:53:13 -0500
Subject: [PATCH] Basics coming together...
---
components/Note.tsx | 21 +++++++++++++++++++++
db/mod.ts | 20 +++++++++++---------
routes/_middleware.ts | 20 ++++++++------------
routes/dashboard.tsx | 16 +++++++++-------
routes/note.tsx | 13 ++-----------
routes/note/create.tsx | 7 ++++---
types.ts | 15 +++++++++++----
7 files changed, 66 insertions(+), 46 deletions(-)
create mode 100644 components/Note.tsx
diff --git a/components/Note.tsx b/components/Note.tsx
new file mode 100644
index 0000000..092a2a8
--- /dev/null
+++ b/components/Note.tsx
@@ -0,0 +1,21 @@
+import { type Note } from "@/types.ts";
+
+export function NoteItem(
+ { id, createdAt, content, userId, userDisplayName, userUsername }: Note,
+) {
+ return (
+
+ );
+}
diff --git a/db/mod.ts b/db/mod.ts
index c4f4333..f260166 100644
--- a/db/mod.ts
+++ b/db/mod.ts
@@ -53,13 +53,15 @@ export async function queryObject(
sql: string,
args?: QueryArguments,
): Promise | null> {
- return await dbOp(async (connection) =>
- await connection.queryObject({
+ return await dbOp(async (connection) => {
+ const result = await connection.queryObject({
camelcase: true,
text: sql.trim(),
args,
- })
- );
+ });
+ console.debug(result);
+ return result;
+ });
}
export async function queryArray(
@@ -76,8 +78,8 @@ export async function queryArray(
export async function listNotes(): Promise {
return someRows(
- await queryObject(
- "select * from note order by created_at desc",
+ await queryObject(
+ 'select u.username as user_username, u.display_name as user_display_name, n.* from note n left join "user" u on u.id = n.user_id order by n.created_at desc',
),
);
}
@@ -98,12 +100,12 @@ export async function getNote(
type Ungenerated = Omit;
export async function createNote(
- { content }: Ungenerated,
+ { content, userId }: Ungenerated,
): Promise {
return singleRow(
await queryObject(
- "insert into note (content) values ($1) returning *",
- [content],
+ "insert into note (content, user_id) values ($1, $2) returning *",
+ [content, userId],
),
);
}
diff --git a/routes/_middleware.ts b/routes/_middleware.ts
index 0553de9..e87521b 100644
--- a/routes/_middleware.ts
+++ b/routes/_middleware.ts
@@ -1,28 +1,24 @@
import { MiddlewareHandlerContext } from "$fresh/server.ts";
import { deleteCookie, getCookies } from "$std/http/cookie.ts";
import { getUserFromNonExpiredLoginToken } from "@/db/mod.ts";
-
-interface State {
- data: string;
-}
+import { type ContextState } from "@/types.ts";
export async function handler(
request: Request,
- ctx: MiddlewareHandlerContext,
+ ctx: MiddlewareHandlerContext,
) {
- ctx.state.data = "";
let hasBadAuthCookie = false;
const { lsauth } = getCookies(request.headers);
console.log("lsauth cookie:", lsauth);
if (lsauth) {
const user = await getUserFromNonExpiredLoginToken(lsauth);
if (!user) hasBadAuthCookie = true;
- else {ctx.state.data += "user:" + JSON.stringify({
- id: user.id,
- username: user.username,
- displayName: user.displayName || user.username,
- }) +
- "\n";}
+ else {
+ ctx.state.user = user;
+ delete ctx.state.user.createdAt;
+ delete ctx.state.user.updatedAt;
+ delete ctx.state.user.passwordDigest;
+ }
}
const resp = await ctx.next();
diff --git a/routes/dashboard.tsx b/routes/dashboard.tsx
index ad64411..301d01e 100644
--- a/routes/dashboard.tsx
+++ b/routes/dashboard.tsx
@@ -1,17 +1,19 @@
-import { HandlerContext, Handlers, PageProps } from "$fresh/server.ts";
+import { Handlers, PageProps } from "$fresh/server.ts";
import { Page } from "@/components/Page.tsx";
// import { getToken, getUser } from "@/db/mod.ts";
// import * as base64 from "$std/encoding/base64.ts";
-import { getCookies } from "$std/http/cookie.ts";
-import { type User } from "@/types.ts";
+import { type ContextState } from "@/types.ts";
-export const handler: Handlers = {
- async GET(request: Request, context) {
- return await context.render(context.state.data);
+export const handler: Handlers = {
+ async GET(_request: Request, context) {
+ const user: Partial = context.state.user;
+ delete user.passwordDigest;
+ return await context.render(context.state.user);
},
};
export default function Dashboard({ data }: PageProps) {
+ console.log(data);
if (data) {
return You(data);
} else {
@@ -23,7 +25,7 @@ function You(data: unknown) {
return (
- You are
{data}
.
+ You are {JSON.stringify(data)}
.
);
diff --git a/routes/note.tsx b/routes/note.tsx
index 8307c78..ae3da0e 100644
--- a/routes/note.tsx
+++ b/routes/note.tsx
@@ -2,6 +2,7 @@ import { Handlers, PageProps } from "$fresh/server.ts";
import { listNotes } from "@/db/mod.ts";
import { Page } from "@/components/Page.tsx";
import { type Note } from "@/types.ts";
+import { NoteItem } from "@/components/Note.tsx";
export const handler: Handlers = {
async GET(_request, context) {
@@ -19,17 +20,7 @@ export default function NotesPage({ data: notes }: PageProps) {
- {notes.map(({ id, content, createdAt }) => (
-
-
- Note {id}{" "}
- created at {createdAt.toLocaleString()}
-
-
- {content}
-
-
- ))}
+ {notes.map(NoteItem)}
);
}
diff --git a/routes/note/create.tsx b/routes/note/create.tsx
index 66fc1da..197619f 100644
--- a/routes/note/create.tsx
+++ b/routes/note/create.tsx
@@ -1,13 +1,14 @@
import { Handlers, PageProps } from "$fresh/server.ts";
import { createNote } from "@/db/mod.ts";
import { Page } from "@/components/Page.tsx";
-import { type Note } from "@/types.ts";
+import { type ContextState, type Note } from "@/types.ts";
-export const handler: Handlers = {
+export const handler: Handlers = {
async POST(request, context) {
+ const userId = context.state.user ? context.state.user.id : null;
const content = (await request.formData()).get("content");
if (!content) throw "no content provided";
- const note = await createNote({ content: content.toString() });
+ const note = await createNote({ userId, content: content.toString() });
if (!note) throw "no note created";
return await context.render(note);
},
diff --git a/types.ts b/types.ts
index ce19b8f..8ca144f 100644
--- a/types.ts
+++ b/types.ts
@@ -12,10 +12,6 @@ export interface Updated {
export type Timestamped = Created & Updated;
-export interface Note extends Identifiable, Timestamped {
- content: string;
-}
-
export interface Team extends Identifiable, Timestamped {
displayName: string;
}
@@ -26,6 +22,13 @@ export interface User extends Identifiable, Timestamped {
displayName?: string;
}
+export interface Note extends Identifiable, Timestamped {
+ content: string;
+ userId: User["id"] | null;
+ userUsername?: User["username"];
+ userDisplayName?: User["displayName"];
+}
+
type IdentifierFor = T["id"];
export interface Token extends Created {
@@ -37,3 +40,7 @@ export interface Token extends Created {
/** 32 bytes base64-encoded */
export type TokenDigest = string;
+
+export interface ContextState {
+ user?: Omit & Partial;
+}