diff --git a/.astro/types.d.ts b/.astro/types.d.ts
index 4c922f7..4edf25a 100644
--- a/.astro/types.d.ts
+++ b/.astro/types.d.ts
@@ -623,5 +623,5 @@ declare module 'astro:content' {
type AnyEntryMap = ContentEntryMap & DataEntryMap;
- type ContentConfig = typeof import("../src/content/config");
+ export type ContentConfig = typeof import("../src/content/config.js");
}
diff --git a/astro.config.mjs b/astro.config.mjs
index 5e7112d..2bedf3a 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -13,40 +13,65 @@ import metaTags from "astro-meta-tags";
// https://astro.build/config
export default defineConfig({
// ...
- integrations: [expressiveCode({
- theme: ["dracula-soft"]
- }), mdx(), react(), metaTags()],
+ integrations: [
+ expressiveCode({
+ theme: ["dracula-soft"],
+ }),
+ mdx(),
+ react(),
+ metaTags(),
+ ],
markdown: {
remarkPlugins: [],
- rehypePlugins: [rehypeSlug, [rehypeAutolinkHeadings, {
- behavior: "wrap"
- }], [rehypeToc, {
- customizeTOC: toc => {
- if (toc.children[0].children?.length > 0) {
- return toc;
- }
- return false;
- },
- customizeTOCItem: (toc, heading) => {
- const headingContent = heading.children?.[0];
- if (headingContent.children.length > 1) {
- toc.children[0].children = headingContent.children;
- }
- return toc;
- }
- }], [rehypeCustomEmoji, {
- emojis: {
- bobaparty: "/emojis/bobaparty.png",
- bobatwt: "/emojis/bobatwt.png",
- bobaeyes: "/emojis/bobaeyes.png"
- },
- className: "custom-emoji"
- }], rehypeAddAltText]
+ rehypePlugins: [
+ rehypeSlug,
+ [
+ rehypeAutolinkHeadings,
+ {
+ behavior: "wrap",
+ },
+ ],
+ [
+ rehypeToc,
+ {
+ customizeTOC: (toc) => {
+ if (toc.children[0].children?.length > 0) {
+ return toc;
+ }
+ return false;
+ },
+ customizeTOCItem: (toc, heading) => {
+ const headingContent = heading.children?.[0];
+ if (headingContent.children.length > 1) {
+ toc.children[0].children = headingContent.children;
+ }
+ return toc;
+ },
+ },
+ ],
+ [
+ rehypeCustomEmoji,
+ {
+ emojis: {
+ bobaparty: "/emojis/bobaparty.png",
+ bobatwt: "/emojis/bobatwt.png",
+ bobaeyes: "/emojis/bobaeyes.png",
+ },
+ className: "custom-emoji",
+ },
+ ],
+ rehypeAddAltText,
+ ],
},
redirects: {
- "/subscribe": "/support-me"
+ "/subscribe": "/support-me",
},
- output: "hybrid",
+ output: "server",
adapter: vercel(),
- site: "https://www.essentialrandomness.com"
-});
\ No newline at end of file
+ site: "https://www.essentialrandomness.com",
+ vite: {
+ optimizeDeps: {
+ exclude: ["oslo"],
+ },
+ },
+});
diff --git a/drizzle.config.ts b/drizzle.config.ts
new file mode 100644
index 0000000..5b3e6b2
--- /dev/null
+++ b/drizzle.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from "drizzle-kit";
+export default defineConfig({
+ schema: "./src/db/schema.ts",
+ out: "./src/db/drizzle",
+ driver: "turso",
+ dbCredentials: {
+ url: process.env.TURSO_DB_LOGIN!,
+ authToken: process.env.TURSO_DB_AUTH,
+ },
+});
diff --git a/package.json b/package.json
index 97b4742..9648c7a 100644
--- a/package.json
+++ b/package.json
@@ -13,16 +13,21 @@
"@astrojs/mdx": "2.0.6",
"@astrojs/react": "3.0.9",
"@astrojs/rss": "^4.0.3",
- "@astrojs/vercel": "^7.0.1",
+ "@astrojs/vercel": "^7.1.1",
+ "@libsql/client": "^0.4.3",
+ "@lucia-auth/adapter-drizzle": "^1.0.0",
"@paypal/paypal-js": "^7.0.0",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
- "astro": "4.2.2",
+ "astro": "^4.3.2",
"astro-expressive-code": "^0.32.2",
"astro-icon": "^0.8.1",
"astro-meta-tags": "^0.2.1",
"clsx": "^2.0.0",
+ "drizzle-orm": "^0.29.3",
+ "lucia": "^3.0.1",
"marked": "^7.0.4",
+ "oslo": "^1.0.4",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-icons": "npm:@lorenzobloedow/react-icons",
@@ -37,6 +42,7 @@
"unist-util-select": "^5.1.0"
},
"devDependencies": {
+ "drizzle-kit": "^0.20.14",
"hast-util-from-html-isomorphic": "^2.0.0",
"postcss-nesting": "^12.0.1",
"prettier": "^3.0.1",
diff --git a/src/auth/createUser.ts b/src/auth/createUser.ts
new file mode 100644
index 0000000..f555b49
--- /dev/null
+++ b/src/auth/createUser.ts
@@ -0,0 +1,15 @@
+// pages/api/signup.ts
+import { generateId } from "lucia";
+import { Argon2id } from "oslo/password";
+import { db } from "../db";
+import { users } from "../db/schema";
+
+const userId = generateId(15);
+const hashedPassword = await new Argon2id().hash("blorbos");
+
+export const createUser = async () =>
+ await db.insert(users).values({
+ id: userId,
+ username: "bobatan",
+ hashed_password: hashedPassword,
+ });
diff --git a/src/auth/index.ts b/src/auth/index.ts
new file mode 100644
index 0000000..aa84458
--- /dev/null
+++ b/src/auth/index.ts
@@ -0,0 +1,30 @@
+import { DrizzleSQLiteAdapter } from "@lucia-auth/adapter-drizzle";
+import { db } from "../db";
+import { sessions, users } from "../db/schema";
+import { Lucia } from "lucia";
+
+declare module "lucia" {
+ interface Register {
+ Lucia: typeof Lucia;
+ DatabaseUserAttributes: DatabaseUserAttributes;
+ }
+}
+
+interface DatabaseUserAttributes {
+ username: string;
+}
+
+const adapter = new DrizzleSQLiteAdapter(db, sessions, users);
+export const auth = new Lucia(adapter, {
+ sessionCookie: {
+ attributes: {
+ secure: import.meta.env.PROD,
+ },
+ },
+ getUserAttributes: (attributes) => {
+ return {
+ // attributes has the type of DatabaseUserAttributes
+ username: attributes.username,
+ };
+ },
+});
diff --git a/src/db/index.ts b/src/db/index.ts
new file mode 100644
index 0000000..9ec76aa
--- /dev/null
+++ b/src/db/index.ts
@@ -0,0 +1,9 @@
+import { drizzle } from "drizzle-orm/libsql";
+import { createClient } from "@libsql/client";
+
+const client = createClient({
+ url: import.meta.env.TURSO_DB_LOGIN!,
+ authToken: import.meta.env.TURSO_DB_AUTH,
+});
+
+export const db = drizzle(client);
diff --git a/src/db/schema.ts b/src/db/schema.ts
new file mode 100644
index 0000000..630a96f
--- /dev/null
+++ b/src/db/schema.ts
@@ -0,0 +1,15 @@
+import { text, integer, sqliteTable, int } from "drizzle-orm/sqlite-core";
+
+export const users = sqliteTable("users", {
+ id: text("id").primaryKey().notNull(),
+ username: text("username").notNull().unique(),
+ hashed_password: text("hashed_password"),
+});
+
+export const sessions = sqliteTable("sessions", {
+ id: text("id").notNull().primaryKey(),
+ userId: text("user_id")
+ .notNull()
+ .references(() => users.id),
+ expiresAt: integer("expires_at").notNull(),
+});
diff --git a/src/env.d.ts b/src/env.d.ts
index acef35f..df02170 100644
--- a/src/env.d.ts
+++ b/src/env.d.ts
@@ -1,2 +1,9 @@
///