Switching to use SQLite instead of MySQL
This commit is contained in:
parent
dd46f61ecc
commit
0c6c9df93f
9 changed files with 1031 additions and 295 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -7,3 +7,6 @@ dist/
|
|||
|
||||
# vscode
|
||||
.vscode/settings.json
|
||||
|
||||
# sqlite
|
||||
autobaan_db
|
||||
|
|
@ -1,16 +1,4 @@
|
|||
services:
|
||||
database:
|
||||
image: mysql:latest
|
||||
restart: always
|
||||
env_file: ./database/.env
|
||||
command: --default-authentication-plugin=mysql_native_password
|
||||
ports:
|
||||
- 3306:3306
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
http:
|
||||
build:
|
||||
context: ..
|
||||
|
|
@ -19,6 +7,5 @@ services:
|
|||
env_file: ./server/.env
|
||||
ports:
|
||||
- 3000:3000
|
||||
depends_on:
|
||||
database:
|
||||
condition: service_healthy
|
||||
# volumes:
|
||||
# - ./autobaan_db:/app/autobaan_db
|
||||
1129
package-lock.json
generated
1129
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -29,14 +29,13 @@
|
|||
"argon2": "^0.30.3",
|
||||
"axios": "^1.2.0",
|
||||
"dayjs": "^1.11.6",
|
||||
"mysql": "^2.18.1",
|
||||
"node-cron": "^3.0.2",
|
||||
"puppeteer": "^19.5.2",
|
||||
"sqlite3": "^5.1.4",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.2.3",
|
||||
"@types/mysql": "^2.15.21",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/node-cron": "^3.0.6",
|
||||
"@types/puppeteer": "^7.0.4",
|
||||
|
|
|
|||
|
|
@ -1,81 +1,34 @@
|
|||
import mysql, { Connection, ConnectionConfig, FieldInfo } from 'mysql'
|
||||
import { TABLE_reservations } from './sql'
|
||||
import { resolve } from 'path'
|
||||
import sqlite from 'sqlite3'
|
||||
import { CREATE_TABLE_reservations } from './sql'
|
||||
|
||||
const createConnectionConfig = async (): Promise<ConnectionConfig> => {
|
||||
const host = process.env.MYSQL_HOST
|
||||
const user = process.env.MYSQL_USER
|
||||
const password = process.env.MYSQL_PASSWORD
|
||||
const database = process.env.MYSQL_DATABASE
|
||||
if (!user || !password || !database) {
|
||||
throw new DatabaseEnvironmentError(
|
||||
'Required environment variables are missing'
|
||||
)
|
||||
}
|
||||
return {
|
||||
host,
|
||||
user,
|
||||
password,
|
||||
database,
|
||||
}
|
||||
}
|
||||
|
||||
let connection: Connection
|
||||
|
||||
export const getConnection = async (): Promise<Connection> => {
|
||||
if (!connection) {
|
||||
const config = await createConnectionConfig()
|
||||
connection = mysql.createConnection(config)
|
||||
}
|
||||
return connection
|
||||
}
|
||||
|
||||
export type ResultSet<T> = T[]
|
||||
|
||||
export const connect = async () => {
|
||||
return new Promise<void>((res, rej) =>
|
||||
getConnection().then((cn) => {
|
||||
cn.connect((err) => {
|
||||
if (err) {
|
||||
rej(err)
|
||||
}
|
||||
res()
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export const disconnect = async () => {
|
||||
return new Promise<void>((res, rej) =>
|
||||
getConnection().then((cn) => {
|
||||
cn.end((err) => {
|
||||
if (err) {
|
||||
rej(err)
|
||||
}
|
||||
res()
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export const query = async <T = unknown, V = unknown>(
|
||||
sql: string,
|
||||
values?: V
|
||||
): Promise<{ results: ResultSet<T>; fields?: FieldInfo[] }> => {
|
||||
return new Promise((res, rej) => {
|
||||
connection.query({ sql, values }, (err, results, fields) => {
|
||||
if (err) {
|
||||
rej(err)
|
||||
}
|
||||
res({ results, fields })
|
||||
export const run = async (sql: string, params?: unknown) => {
|
||||
const db = new sqlite.Database(resolve('autobaan_db'))
|
||||
await new Promise<void>((res, rej) => {
|
||||
db.run(sql, params, (err) => {
|
||||
if (err) rej(err)
|
||||
res()
|
||||
})
|
||||
})
|
||||
db.close()
|
||||
}
|
||||
|
||||
export const all = async <T>(sql: string, params?: unknown) => {
|
||||
const db = new sqlite.Database(resolve('autobaan_db'))
|
||||
const rows = await new Promise<T[]>((res, rej) =>
|
||||
db.all(sql, params, (err, rows) => {
|
||||
if (err) rej(err)
|
||||
res(rows)
|
||||
})
|
||||
)
|
||||
db.close()
|
||||
return rows
|
||||
}
|
||||
|
||||
export const init = async () => {
|
||||
try {
|
||||
await connect()
|
||||
await query(TABLE_reservations)
|
||||
} catch (err: any) {
|
||||
await run(CREATE_TABLE_reservations)
|
||||
} catch (err: unknown) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export const TABLE_reservations = `
|
||||
export const CREATE_TABLE_reservations = `
|
||||
CREATE TABLE IF NOT EXISTS reservations (
|
||||
id VARCHAR(36) NOT NULL PRIMARY KEY,
|
||||
username VARCHAR(64) NOT NULL UNIQUE,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Dayjs } from 'dayjs'
|
||||
import { v4 } from 'uuid'
|
||||
import dayjs from './dayjs'
|
||||
import { query } from './database'
|
||||
import { all, run } from './database'
|
||||
|
||||
const RESERVATION_AVAILABLE_WITHIN_DAYS = 7
|
||||
|
||||
|
|
@ -127,7 +127,7 @@ export class Reservation {
|
|||
}
|
||||
|
||||
public static async save(res: Reservation) {
|
||||
await query(
|
||||
await run(
|
||||
`
|
||||
INSERT INTO reservations
|
||||
(
|
||||
|
|
@ -163,19 +163,17 @@ export class Reservation {
|
|||
}
|
||||
|
||||
public static async delete(res: Reservation) {
|
||||
await query(
|
||||
await run(
|
||||
`
|
||||
DELETE FROM reservations
|
||||
WHERE id = $
|
||||
`,
|
||||
[
|
||||
res.id,
|
||||
]
|
||||
[res.id]
|
||||
)
|
||||
}
|
||||
|
||||
public static async fetchById(id: string): Promise<Reservation | null> {
|
||||
const response = await query<SqlReservation>(
|
||||
const response = await all<SqlReservation>(
|
||||
`
|
||||
SELECT *
|
||||
FROM reservations
|
||||
|
|
@ -184,8 +182,8 @@ export class Reservation {
|
|||
[id]
|
||||
)
|
||||
|
||||
if (response.results.length === 1) {
|
||||
const sqlReservation = response.results[0]
|
||||
if (response.length === 1) {
|
||||
const sqlReservation = response[0]
|
||||
const res = new Reservation(
|
||||
{
|
||||
username: sqlReservation.username,
|
||||
|
|
@ -197,7 +195,7 @@ export class Reservation {
|
|||
},
|
||||
{ id: sqlReservation.opponent_id, name: sqlReservation.opponent_name },
|
||||
undefined,
|
||||
sqlReservation.id,
|
||||
sqlReservation.id
|
||||
)
|
||||
return res
|
||||
}
|
||||
|
|
@ -206,7 +204,7 @@ export class Reservation {
|
|||
}
|
||||
|
||||
public static async fetchFirst(): Promise<Reservation | null> {
|
||||
const response = await query<SqlReservation>(
|
||||
const response = await all<SqlReservation>(
|
||||
`
|
||||
SELECT *
|
||||
FROM reservations
|
||||
|
|
@ -215,8 +213,8 @@ export class Reservation {
|
|||
`
|
||||
)
|
||||
|
||||
if (response.results.length === 1) {
|
||||
const sqlReservation = response.results[0]
|
||||
if (response.length === 1) {
|
||||
const sqlReservation = response[0]
|
||||
const res = new Reservation(
|
||||
{
|
||||
username: sqlReservation.username,
|
||||
|
|
@ -228,7 +226,7 @@ export class Reservation {
|
|||
},
|
||||
{ id: sqlReservation.opponent_id, name: sqlReservation.opponent_name },
|
||||
undefined,
|
||||
sqlReservation.id,
|
||||
sqlReservation.id
|
||||
)
|
||||
return res
|
||||
}
|
||||
|
|
@ -236,8 +234,11 @@ export class Reservation {
|
|||
return null
|
||||
}
|
||||
|
||||
public static async fetchByDate(date: Dayjs, limit = 20): Promise<Reservation[]> {
|
||||
const response = await query<SqlReservation>(
|
||||
public static async fetchByDate(
|
||||
date: Dayjs,
|
||||
limit = 20
|
||||
): Promise<Reservation[]> {
|
||||
const response = await all<SqlReservation>(
|
||||
`
|
||||
SELECT *
|
||||
FROM reservations
|
||||
|
|
@ -245,26 +246,29 @@ export class Reservation {
|
|||
ORDER BY date_range_start DESC
|
||||
LIMIT ?;
|
||||
`,
|
||||
[
|
||||
date.format('YYYY-MM-DD'),
|
||||
limit,
|
||||
]
|
||||
[date.format('YYYY-MM-DD'), limit]
|
||||
)
|
||||
|
||||
if (response.results.length > 0) {
|
||||
return response.results.map((sqlReservation) => new Reservation(
|
||||
{
|
||||
username: sqlReservation.username,
|
||||
password: sqlReservation.password,
|
||||
},
|
||||
{
|
||||
start: dayjs(sqlReservation.date_range_start),
|
||||
end: dayjs(sqlReservation.date_range_end),
|
||||
},
|
||||
{ id: sqlReservation.opponent_id, name: sqlReservation.opponent_name },
|
||||
undefined,
|
||||
sqlReservation.id,
|
||||
))
|
||||
if (response.length > 0) {
|
||||
return response.map(
|
||||
(sqlReservation) =>
|
||||
new Reservation(
|
||||
{
|
||||
username: sqlReservation.username,
|
||||
password: sqlReservation.password,
|
||||
},
|
||||
{
|
||||
start: dayjs(sqlReservation.date_range_start),
|
||||
end: dayjs(sqlReservation.date_range_end),
|
||||
},
|
||||
{
|
||||
id: sqlReservation.opponent_id,
|
||||
name: sqlReservation.opponent_name,
|
||||
},
|
||||
undefined,
|
||||
sqlReservation.id
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return []
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { disconnect, init } from '../common/database'
|
||||
import { init } from '../common/database'
|
||||
import { Logger, LogLevel } from '../common/logger'
|
||||
import server from './http'
|
||||
import { startTasks, stopTasks } from './cron'
|
||||
|
|
@ -14,7 +14,6 @@ process.on('uncaughtException', (error, origin) => {
|
|||
})
|
||||
|
||||
process.on('beforeExit', async () => {
|
||||
await disconnect()
|
||||
stopTasks()
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ describe('scheduler', () => {
|
|||
{ start, end },
|
||||
{ id: '123', name: 'collin' },
|
||||
undefined,
|
||||
'1234',
|
||||
'1234'
|
||||
),
|
||||
scheduledFor: start
|
||||
.subtract(7, 'days')
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue