commit 2258b651deb2417b100d80f2a6785dc0be9e1e74 Author: Dave Smith-Hayes Date: Fri Feb 16 18:19:58 2024 -0500 init slovocast API later. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f542aff --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,16 @@ +version: '3.9' + +services: + database: + image: mariadb:latest + environment: + ROOT_MYSQL_PASSWORD: password + MYSQL_USER: user + MYSQL_PASSWORD: password + MYSQL_DATABASE: slovocast + ports: + - "3306:3306" + volumes: + - slovocast_db:/var/lib/mysql +volumes: + slovocast_db: diff --git a/frontend/.gitkeep b/frontend/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/server/.env b/server/.env new file mode 100644 index 0000000..738da5f --- /dev/null +++ b/server/.env @@ -0,0 +1,4 @@ +DATABASE_HOST=localhost +DATABASE_USER=user +DATABASE_PASSWORD=password +DATABASE_SCHEMA=slovocast diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/server/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/server/README.md b/server/README.md new file mode 100644 index 0000000..6dd13e7 --- /dev/null +++ b/server/README.md @@ -0,0 +1,11 @@ +To install dependencies: +```sh +bun install +``` + +To run: +```sh +bun run dev +``` + +open http://localhost:3000 diff --git a/server/bun.lockb b/server/bun.lockb new file mode 100755 index 0000000..766be32 Binary files /dev/null and b/server/bun.lockb differ diff --git a/server/package.json b/server/package.json new file mode 100644 index 0000000..4019037 --- /dev/null +++ b/server/package.json @@ -0,0 +1,13 @@ +{ + "scripts": { + "dev": "bun run --hot src/index.ts" + }, + "dependencies": { + "hono": "^4.0.3", + "mariadb": "^3.2.3", + "podcast": "^2.0.1" + }, + "devDependencies": { + "@types/bun": "latest" + } +} diff --git a/server/sql/drop_tables.sql b/server/sql/drop_tables.sql new file mode 100644 index 0000000..c99ddcd --- /dev/null +++ b/server/sql/drop_tables.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS users; diff --git a/server/sql/users.sql b/server/sql/users.sql new file mode 100644 index 0000000..316eeed --- /dev/null +++ b/server/sql/users.sql @@ -0,0 +1,10 @@ +CREATE TABLE users ( + id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + username VARCHAR(255) NOT NULL, + password VARCHAR(255) NOT NULL, + + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + PRIMARY KEY(`id`) +); diff --git a/server/src/index.ts b/server/src/index.ts new file mode 100644 index 0000000..22719bf --- /dev/null +++ b/server/src/index.ts @@ -0,0 +1,61 @@ +import { Context, Hono } from 'hono'; +import { Connection, createPool } from 'mariadb'; + +import User from './models/User'; + +const app = new Hono(); + +// +// bootstrap resources +// + +// mariadb +const databasePool = createPool({ + host: process.env.DATABASE_HOST, + user: process.env.DATABASE_USER, + password: process.env.DATABASE_PASSWORD, + database: process.env.DATABASE_SCHEMA +}); + +app.onError((err: Error, c: Context) => { + console.log(err.message); + c.status(500); + + if (process.env.MODE == 'development') { + return c.json({ err }); + } + + return c.json({ message: "An error occurred." }); +}) + +// +// set routes +// + +// Welcome message +app.get('/', async (c: Context) => { + return c.json({ + message: "Hello from Slovocast" + }); +}); + +// User actions +import users from './routes/user'; +app.route("/users", users); + +// Channel Actions + // add episode + // edit episode + // regenerate feed +app.get('/:channel', (c: Context) => { + return c.json({ + channel: { + name: "Name", + } + }); +}); + + +// feed actions +console.log("Running app on :3000"); +export default app; diff --git a/server/src/infrastructure/database.ts b/server/src/infrastructure/database.ts new file mode 100644 index 0000000..df0549a --- /dev/null +++ b/server/src/infrastructure/database.ts @@ -0,0 +1,36 @@ +import { Connection, Pool, createPool } from 'mariadb'; + +type ConnectionConfig = { + host: string, + user: string, + password: string, + database: string, + port: number, +}; + +export default class Database { + private static instance: Database; + private pool: Pool; + + private constructor(config: ConnectionConfig) { + this.pool = createPool(config); + } + + public static getInstance(): Database { + if (!Database.instance) { + Database.instance = new Database({ + host: process.env.DATABASE_HOST as string, + user: process.env.DATABASE_USER as string, + password: process.env.DATABASE_PASSWORD as string, + database: process.env.DATABASE_SCHEMA as string, + port: 3306 + }); + } + + return Database.instance; + } + + public async getConnection(): Promise { + return this.pool.getConnection(); + } +} diff --git a/server/src/models/Channel.ts b/server/src/models/Channel.ts new file mode 100644 index 0000000..64adf08 --- /dev/null +++ b/server/src/models/Channel.ts @@ -0,0 +1,12 @@ +export default class Channel { + private name: string; + private slug: string; + + private constructor(name: string) { + this.name = name; + } + + public static generateSlug(name: string): string { + return name; + } +} diff --git a/server/src/models/User.ts b/server/src/models/User.ts new file mode 100644 index 0000000..96f8b7f --- /dev/null +++ b/server/src/models/User.ts @@ -0,0 +1,8 @@ +type User = { + username: string, + password: string, + + name: string, +}; + +export default User; diff --git a/server/src/routes/user.ts b/server/src/routes/user.ts new file mode 100644 index 0000000..64ba7c7 --- /dev/null +++ b/server/src/routes/user.ts @@ -0,0 +1,38 @@ +import { Hono, Context } from 'hono'; +import { Connection } from 'mariadb'; +import User from '@slovo/models/User'; +import Database from '@slovo/infrastructure/database'; + +const app = new Hono(); + +// add routes and methods here +app.post('/register', async (c: Context) => { + // check if form (from the web app) or JSON (from a blank API call); + let user: User; + if (c.req.header('Content-Type') == 'application/json') { + user = await c.req.json(); + } else { + user = await c.req.formData(); + } + + + const conn: Connection = await Database.getInstance().getConnection(); + const query = `INSERT INTO users (username, password) VALUES (?, ?)`; + + try { + const results = await conn.query(query, [ user.username, user.password ]); + + console.log(results); + return c.json({ + message: "Registration successful.", + }); + } catch (e) { + console.error(e); + c.status(500); + return c.json({ + message: "Error registering user." + }); + } +}); + +export default app; diff --git a/server/src/setup.ts b/server/src/setup.ts new file mode 100644 index 0000000..1275cb8 --- /dev/null +++ b/server/src/setup.ts @@ -0,0 +1,27 @@ +import { createPool } from "mariadb"; + +async function run() { + const pool = createPool({ + host: process.env.DATABASE_HOST, + user: process.env.DATABASE_USER, + password: process.env.DATABASE_PASSWORD, + database: process.env.DATABASE_SCHEMA + }); + + const createUserBuffer: string = await Bun.file('./sql/users.sql').text(); + const conn = await pool.getConnection(); + const results = await conn.query(createUserBuffer); + + return results; +} + +run() + .then(r => { + console.log(r); + process.exit(0); + }) + .catch(e => { + console.error(e); + process.exit(1); + }) + diff --git a/server/tsconfig.json b/server/tsconfig.json new file mode 100644 index 0000000..98da342 --- /dev/null +++ b/server/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "strict": true, + "jsx": "react-jsx", + "jsxImportSource": "hono/jsx" + }, + "paths": { + "@slovo/*": [ "./src/*" ] + } +}