Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
node_modules/
.husky/
.github/
.nitro/
.output/
Expand Down
34 changes: 7 additions & 27 deletions .env
Original file line number Diff line number Diff line change
@@ -1,33 +1,13 @@
API_BASE_URL=http://localhost:3000
DEBUG=true

# filesystem
STORAGE_DRIVER=filesystem
STORAGE_FILESYSTEM_PATH=.data/storage/filesystem

# s3
# STORAGE_DRIVER=s3
# STORAGE_S3_BUCKET=test
# AWS_ENDPOINT_URL=http://minio:9000
# AWS_ACCESS_KEY_ID=minioadmin
# AWS_SECRET_ACCESS_KEY=minioadmin

# sqlite
DB_DRIVER=sqlite
DB_SQLITE_PATH=.data/sqlite.db
STORAGE_DRIVER=s3
STORAGE_S3_BUCKET=test
AWS_ENDPOINT_URL=http://localhost:9000
AWS_ACCESS_KEY_ID=access_key
AWS_SECRET_ACCESS_KEY=secret_key

# postgres
# DB_DRIVER=postgres
# DB_POSTGRES_DATABASE=postgres
# DB_POSTGRES_HOST=localhost
# DB_POSTGRES_USER=postgres
# DB_POSTGRES_PASSWORD=postgres
# DB_POSTGRES_PORT=5432

# mysql
# DB_DRIVER=mysql
# DB_MYSQL_DATABASE=mysql
# DB_MYSQL_HOST=localhost
# DB_MYSQL_USER=root
# DB_MYSQL_PASSWORD=root
# DB_MYSQL_PORT=3306
DB_DRIVER=postgres
DB_POSTGRES_URL=postgres://postgres:postgres@localhost:5432/postgres
3 changes: 2 additions & 1 deletion .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ name: 🚥 CI/CD
on:
workflow_dispatch:
push:
branches: '**'
branches:
- '**'
pull_request:
branches:
- dev
Expand Down
2 changes: 0 additions & 2 deletions .husky/commit-msg

This file was deleted.

2 changes: 0 additions & 2 deletions .husky/pre-commit

This file was deleted.

10 changes: 0 additions & 10 deletions .lintstagedrc.mjs

This file was deleted.

1 change: 0 additions & 1 deletion .prettierrc.cjs

This file was deleted.

6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:22-alpine AS builder
FROM node:24-alpine AS builder

WORKDIR /app

Expand All @@ -8,15 +8,15 @@ COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
RUN --mount=type=cache,target=/root/.local/share/pnpm/store pnpm fetch --prod

COPY . .
RUN pnpm install --frozen-lockfile --prod --offline
RUN --mount=type=cache,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile --prod --offline

ARG BUILD_HASH
ENV BUILD_HASH=${BUILD_HASH}
RUN pnpm run build

# --------------------------------------------

FROM node:22-alpine AS runner
FROM node:24-alpine AS runner

ENV NITRO_CLUSTER_WORKERS=1

Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ services:
- '3000:3000'
environment:
API_BASE_URL: http://localhost:3000
STORAGE_DRIVER: filesystem
STORAGE_FILESYSTEM_PATH: /data/cache
DB_DRIVER: sqlite
DB_SQLITE_PATH: /data/cache-server.db
volumes:
- cache-data:/app/.data
- cache-data:/data

volumes:
cache-data:
Expand Down
3 changes: 0 additions & 3 deletions commitlint.config.cjs

This file was deleted.

47 changes: 24 additions & 23 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,40 @@ services:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres

mysql:
image: mysql:8
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mysql
# mysql:
# image: mysql:8
# ports:
# - 3306:3306
# environment:
# MYSQL_ROOT_PASSWORD: root
# MYSQL_DATABASE: mysql

minio:
image: quay.io/minio/minio:latest
entrypoint: sh
command: -c 'mkdir -p /data/test && /usr/bin/minio server /data'
command: -c 'mkdir -p /data/test && /usr/bin/minio server /data --console-address ":9001"'
ports:
- 9000:9000
- 9001:9001
environment:
MINIO_ROOT_USER: access_key
MINIO_ROOT_PASSWORD: secret_key

cache-server:
build:
dockerfile: Dockerfile
context: .
ports:
- '3000:3000'
depends_on:
- minio
# cache-server:
# build:
# dockerfile: Dockerfile
# context: .
# ports:
# - '3000:3000'
# depends_on:
# - minio

environment:
API_BASE_URL: http://localhost:3000
# environment:
# API_BASE_URL: http://localhost:3000

STORAGE_DRIVER: s3
STORAGE_S3_BUCKET: test
# STORAGE_DRIVER: s3
# STORAGE_S3_BUCKET: test

AWS_ACCESS_KEY_ID: access_key
AWS_SECRET_ACCESS_KEY: secret_key
AWS_ENDPOINT_URL: http://minio:9000
# AWS_ACCESS_KEY_ID: access_key
# AWS_SECRET_ACCESS_KEY: secret_key
# AWS_ENDPOINT_URL: http://minio:9000
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// @ts-check
import eslintConfig from '@louishaftmann/eslint-config'
import eslintConfig from '@falcondev-oss/configs/eslint'

export default eslintConfig({
nuxt: false,
Expand Down
139 changes: 139 additions & 0 deletions lib/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/* eslint-disable no-shadow */
import { mkdir } from 'node:fs/promises'
import path from 'node:path'
import { createSingletonPromise } from '@antfu/utils'
import SQLite from 'better-sqlite3'
import { Kysely, Migrator, MysqlDialect, PostgresDialect, SqliteDialect } from 'kysely'
import { createPool } from 'mysql2'
import pg from 'pg'
import { match } from 'ts-pattern'
import { env } from './env'
import { logger } from './logger'
import { migrations } from './migrations'

interface CacheEntry {
id: string
key: string
version: string
updatedAt: number
locationId: string
}

export interface StorageLocation {
id: string
folderName: string
/**
* Number of parts uploaded for this entry or null if parts have already been combined
*/
partCount: number
mergeStartedAt: number | null
mergedAt: number | null
partsDeletedAt: number | null
lastDownloadedAt: number | null
}

interface Upload {
id: number
key: string
version: string
createdAt: number
lastPartUploadedAt: number | null
folderName: string
}

export interface Database {
cache_entries: CacheEntry
storage_locations: StorageLocation
uploads: Upload
}

const dbLogger = logger.withTag('db')

export const getDatabase = createSingletonPromise(async () => {
const dialect = await match(env)
.with({ DB_DRIVER: 'postgres' }, async (env) => {
const pool = new pg.Pool({
database: env.DB_POSTGRES_DATABASE,
host: env.DB_POSTGRES_HOST,
password: env.DB_POSTGRES_PASSWORD,
port: env.DB_POSTGRES_PORT,
user: env.DB_POSTGRES_USER,
max: 10,
})
await pool.connect()

return new PostgresDialect({
pool,
})
})
.with(
{
DB_DRIVER: 'mysql',
},
async (env) => {
const pool = createPool({
database: env.DB_MYSQL_DATABASE,
host: env.DB_MYSQL_HOST,
password: env.DB_MYSQL_PASSWORD,
port: env.DB_MYSQL_PORT,
user: env.DB_MYSQL_USER,
connectionLimit: 10,
})

return new MysqlDialect({
pool,
})
},
)
.with(
{
DB_DRIVER: 'sqlite',
},
async (env) => {
await mkdir(path.dirname(env.DB_SQLITE_PATH), { recursive: true })
return new SqliteDialect({
database: new SQLite(env.DB_SQLITE_PATH),
})
},
)
.exhaustive()

const db = new Kysely<Database>({
dialect,
log: (event) => {
if (event.level === 'error')
dbLogger.error('Query failed', {
durationMs: event.queryDurationMillis,
error: event.error,
sql: event.query.sql,
params: event.query.parameters,
})
else if (event.level === 'query' && env.DEBUG)
dbLogger.debug('Executed query', {
durationMs: event.queryDurationMillis,
sql: event.query.sql,
params: event.query.parameters,
})
},
})

logger.info('Migrating database...')
const migrator = new Migrator({
db,
provider: {
async getMigrations() {
return migrations(env.DB_DRIVER)
},
},
})
const { error, results } = await migrator.migrateToLatest()
if (error) {
logger.error('Database migration failed', error)
// eslint-disable-next-line unicorn/no-process-exit
process.exit(1)
}
logger.debug('Migration results', results)
logger.success('Database migrated')

return db
})
26 changes: 0 additions & 26 deletions lib/db/defineDatabaseDriver.ts

This file was deleted.

16 changes: 0 additions & 16 deletions lib/db/drivers/index.ts

This file was deleted.

Loading