publishing
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
SPARK_PORT=7654
|
||||||
|
DB_FILE_NAME=./spark.db
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
node_modules
|
||||||
|
bun.lock
|
||||||
|
spark.db
|
||||||
|
.DS_Store
|
||||||
|
.env
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import {defineConfig} from "drizzle-kit";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
out: "./drizzle",
|
||||||
|
schema: "./src/db/schema.ts",
|
||||||
|
dialect: "sqlite",
|
||||||
|
dbCredentials: {
|
||||||
|
url: process.env.DB_FILE_NAME!
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@libsql/client": "^0.17.3",
|
||||||
|
"bun": "^1.3.13",
|
||||||
|
"drizzle-orm": "^0.45.2",
|
||||||
|
"express": "^5.2.1",
|
||||||
|
"zod": "^4.4.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/express": "^5.0.6",
|
||||||
|
"@types/node": "^25.6.2",
|
||||||
|
"bun-types": "^1.3.13",
|
||||||
|
"drizzle-kit": "^0.31.10"
|
||||||
|
},
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"scripts": {
|
||||||
|
"start": "bun run src/index.ts",
|
||||||
|
"dev": "bun run --watch src/index.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { drizzle } from "drizzle-orm/bun-sqlite";
|
||||||
|
import path from "node:path";
|
||||||
|
export default drizzle(path.join(__dirname, "../..", process.env.DB_FILE_NAME!));
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { sql } from "drizzle-orm";
|
||||||
|
import { int, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||||
|
|
||||||
|
export const ideasTable = sqliteTable("ideas", {
|
||||||
|
id: int().primaryKey({autoIncrement: true}),
|
||||||
|
createdAt: int("created_at", {mode: "timestamp"}).default(sql`(unixepoch())`).notNull(),
|
||||||
|
updatedAt: int("updated_at", {mode: "timestamp"}).default(sql`(unixepoch())`).notNull(),
|
||||||
|
|
||||||
|
name: text().notNull(),
|
||||||
|
description: text(),
|
||||||
|
notes: text()
|
||||||
|
})
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import db from "../db";
|
||||||
|
import { ideasTable } from "../db/schema";
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
|
||||||
|
export default async function getIdeasHandler(req: Request, res: Response) {
|
||||||
|
const ideas = await db.select().from(ideasTable);
|
||||||
|
res.json(ideas);
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import z from "zod";
|
||||||
|
import { newIdeaSchema, TypedRequest } from "../schemas";
|
||||||
|
import { Response } from "express";
|
||||||
|
import db from "../db";
|
||||||
|
import { ideasTable } from "../db/schema";
|
||||||
|
|
||||||
|
export default async function newIdeaHandler(req: TypedRequest<z.output<typeof newIdeaSchema>>, res: Response) {
|
||||||
|
const {name, description, notes} = req.body;
|
||||||
|
await db.insert(ideasTable).values({
|
||||||
|
name: name || "",
|
||||||
|
description: description || "",
|
||||||
|
notes: notes || ""
|
||||||
|
})
|
||||||
|
res.status(201).json({message: "Idea created"})
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Request, Response } from "express";
|
||||||
|
import db from "../db";
|
||||||
|
import { ideasTable } from "../db/schema";
|
||||||
|
|
||||||
|
export default async function previewIdeasHandler(req: Request, res: Response) {
|
||||||
|
const ideas = await db.select({
|
||||||
|
id: ideasTable.id,
|
||||||
|
name: ideasTable.name,
|
||||||
|
description: ideasTable.description,
|
||||||
|
updatedAt: ideasTable.updatedAt,
|
||||||
|
}).from(ideasTable);
|
||||||
|
res.json(ideas);
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import express from "express"
|
||||||
|
import { newIdeaSchema, validateSchema } from "./schemas";
|
||||||
|
import newIdeaHandler from "./handlers/newIdea";
|
||||||
|
import getIdeasHandler from "./handlers/getIdeas";
|
||||||
|
import previewIdeasHandler from "./handlers/previewIdeas";
|
||||||
|
const spark = express();
|
||||||
|
|
||||||
|
spark.use(express.json());
|
||||||
|
|
||||||
|
spark.post("/idea", validateSchema(newIdeaSchema), newIdeaHandler);
|
||||||
|
spark.get("/idea", getIdeasHandler);
|
||||||
|
spark.get("/idea/preview", previewIdeasHandler);
|
||||||
|
|
||||||
|
const PORT: number = Number(process.env.SPARK_PORT || 7654);
|
||||||
|
spark.listen(PORT, () => {
|
||||||
|
console.log(`Listening on port ${PORT}`)
|
||||||
|
})
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { NextFunction, RequestHandler, Response } from "express";
|
||||||
|
import z from "zod";
|
||||||
|
|
||||||
|
//#region Credit to Galtzabari
|
||||||
|
export interface TypedRequest<T> extends Express.Request {
|
||||||
|
body: T;
|
||||||
|
}
|
||||||
|
export const validateSchema = <T extends z.ZodTypeAny>(schema: T): RequestHandler => {
|
||||||
|
return (
|
||||||
|
req: TypedRequest<z.output<T>>,
|
||||||
|
res: Response,
|
||||||
|
next: NextFunction
|
||||||
|
): void => {
|
||||||
|
const validationResult = schema.safeParse(req.body);
|
||||||
|
|
||||||
|
if (!validationResult.success) {
|
||||||
|
res.status(400).json({
|
||||||
|
message: "Validation failed",
|
||||||
|
errors: validationResult.error!.issues,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite the req.body with validated data
|
||||||
|
req.body = validationResult.data;
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
export const newIdeaSchema = z.object({
|
||||||
|
name: z.string().optional(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
notes: z.string().optional()
|
||||||
|
})
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": [
|
||||||
|
"bun-types"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user