-
Notifications
You must be signed in to change notification settings - Fork 2
Add swarm leaderboard backend with DB #669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
AryanGodara
wants to merge
52
commits into
master
Choose a base branch
from
aryan/swarm-leadership-page-mvp
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
253fde3
initial commit, set up the the directory, and integrate with the repo
AryanGodara 16b3af2
working hono server with kysely and bun:sqlite dummy db, with API end…
AryanGodara 0a2daf1
add and integrate leaderboard-frontend, forked from demo-react, and s…
AryanGodara b3bae3f
add tables and schema for swarms, in progress [skip ci]
AryanGodara 0eee30a
update app names for frontend and backend [skip ci]
AryanGodara ed02bfc
remove unused deps from frontend, temp update bg[skip ci]
AryanGodara d1d92ba
fix naming of db types to be more consistent, minor formatting fixes …
AryanGodara 71319e1
add hono-sessions [skip ci]
AryanGodara 0ed33dc
add stub components for leaderboards [skip ci]
AryanGodara efdd304
more refactoring of the server, trying to add zod validator, and sett…
AryanGodara 72983aa
more refactoring of the server, lots of changes, add migrations setup…
AryanGodara fa8a9f0
refactor repositories [skip ci]
AryanGodara 45360a7
completed users endpoint, tested locally [skip ci]
AryanGodara a6f1d7c
rename some files, add example CURL commands, add DELETE endpoint, in…
AryanGodara 1e0b3f8
finalize delete endpoint and userSchemas [skip ci]
AryanGodara 1234d6b
add guilds and users endpoints [skip ci]
AryanGodara 07ea6b9
guilds API fixing in progress [skip ci]
AryanGodara 2c039b3
add game schema [skip ci]
AryanGodara cffeaff
complete schema, tables, API, and migrations file [skip ci]
AryanGodara 6750ee5
completed User and Wallet Repository [skip ci]
AryanGodara cc3dcdb
all the validation schemas and repository functions, pending URL rout…
AryanGodara 62b21f1
all the validation schemas and repository functions, pending URL rout…
AryanGodara cbcd0f2
add users and guilds URL routes [skip ci]
AryanGodara 22c968b
add leaderboard routes, backend complete, review pending
AryanGodara 9e6a470
do chaining of routes, when exporting subrouters [skip ci]
AryanGodara bf35989
export AppType for rpc, fix bugs, server running, tested some endpoin…
AryanGodara 8e6986e
remove tailwind from leaderboard-frontend, keep codebase minimal[skip…
AryanGodara e1e1fbc
user creation, display and update with profile page
AryanGodara 4dca9fc
in progress, guilds page [skip ci]
AryanGodara cb3abf2
partially done, guilds page [skip ci]
AryanGodara 8fff82b
comlete guilds functionality [skip ci]
AryanGodara f9fbe88
boilerplate for games page [skip ci]
AryanGodara 54a7bf2
remove frontend code, reserve for another PR [skip ci]
AryanGodara a36ec64
remove leaderboard-frontend from bun.lock [skip ci]
AryanGodara 319afda
update game routes, add more routes [skip ci]
AryanGodara 782c3f4
update game score routes [skip ci]
AryanGodara 149af51
rebase and update bun.lock
AryanGodara cfb1e42
refactored hono app, added docs endpoints stub, another minor changes…
AryanGodara c56f6b0
mid refactor, enable swagger openAPI docs in user routes [skip ci]
AryanGodara f556c21
mid refactor, refactoring schemas for user routes [skip ci]
AryanGodara 3aa8dbf
complete user routes refactoring [skip ci]
AryanGodara 1470f6a
mid refactor: refactoring guild routes[skip ci]
AryanGodara 795f19a
refactor guilds routes [skip ci]
AryanGodara d786763
refactor leaderboard and game routes
AryanGodara d7e90b3
more refactors [skip ci]
AryanGodara 7521308
update deps [skip ci]
AryanGodara 05d3a87
refactor: update ID params from number to string and remove redundant…
AryanGodara d3335f9
fix: add missing timestamp fields when creating users, games, guilds …
AryanGodara cf47c63
feat: implement environment variable validation with zod schema [skip…
AryanGodara 30ef8a8
remove redundant apispec.md file [skip ci]
AryanGodara ab58a13
fix: parse numeric query params and game IDs to integers in leaderboa…
AryanGodara 74cfd9a
chore: fix bun.lock conflicts after rebase[skip ci]
AryanGodara File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
PORT=4545 | ||
LEADERBOARD_DB_URL="leaderboard-backend.sqlite" | ||
DATABASE_MIGRATE_DIR="migrations" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
include ../../makefiles/lib.mk | ||
include ../../makefiles/bundling.mk | ||
include ../../makefiles/formatting.mk | ||
include ../../makefiles/help.mk | ||
|
||
# include .env file and export its env vars | ||
# (-include to ignore error if it does not exist) | ||
-include .env | ||
|
||
dev: node_modules reset-dev | ||
@NODE_ENV=development bun --bun --hot src/index.ts; | ||
.PHONY: dev | ||
|
||
prod: build ## Start the local dev server for development | ||
@NODE_ENV=production bun --bun run build/index.es.js; | ||
.PHONY: prod | ||
|
||
# Migration targets for leaderboard-backend (using Bun) | ||
|
||
migrate: ## Runs latest migrations | ||
@echo "Running latest migrations..." | ||
@bun run src/db/migrate.ts | ||
.PHONY: migrate | ||
|
||
migrate-fresh: ## Deletes database and starts fresh | ||
@if [ -f ${LEADERBOARD_DB_URL} ]; then rm ${LEADERBOARD_DB_URL}; fi; | ||
@echo "Running latest migrations on fresh DB..." | ||
@bun run src/db/migrate.ts | ||
.PHONY: migrate-fresh | ||
|
||
# NOTE: migrate-rollback is not implemented in migrate.ts; add support if needed | ||
migrate-rollback: ## Rollsback latest migrations (not implemented) | ||
@echo "Rollback not implemented in migrate.ts. Implement if needed." | ||
.PHONY: migrate-rollback |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# leaderboard-backend | ||
|
||
## Quickstart | ||
|
||
- `make setup` — Install dependencies | ||
- `make dev` — Start the dev server with hot reload | ||
- `make build` — Build the service for production | ||
- `make prod` — Run the built app in production mode | ||
- `make migrate` — Run database migrations (customize as needed) | ||
- `make migrate-fresh` — Reset and re-run migrations | ||
- `make migrate-rollback` — Roll back the last migration |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"$schema": "../../node_modules/@biomejs/biome/configuration_schema.json", | ||
"extends": ["../../support/configs/biome.jsonc"] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { defineConfig } from "@happy.tech/happybuild" | ||
|
||
export default defineConfig({ | ||
bunConfig: { | ||
target: "bun", | ||
minify: false, | ||
}, | ||
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{ | ||
"version": "0.1.0", | ||
"name": "@happy.tech/leaderboard-backend", | ||
"private": true, | ||
"main": "./dist/index.es.js", | ||
"module": "./dist/index.es.js", | ||
"type": "module", | ||
"types": "./dist/index.es.d.ts", | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.es.d.ts", | ||
"default": "./dist/index.es.js" | ||
} | ||
}, | ||
"devDependencies": { | ||
"@happy.tech/common": "workspace:0.1.0", | ||
"@happy.tech/configs": "workspace:0.1.0", | ||
"@happy.tech/happybuild": "workspace:0.1.1", | ||
"@types/bun": "latest" | ||
}, | ||
"peerDependencies": { | ||
"typescript": "^5.0.0" | ||
}, | ||
"dependencies": { | ||
"@hono/zod-openapi": "^0.19.6", | ||
"@hono/zod-validator": "^0.4.3", | ||
"@scalar/hono-api-reference": "^0.8.8", | ||
"hono": "^4.7.2", | ||
"hono-openapi": "^0.4.4", | ||
"kysely": "^0.27.5", | ||
"kysely-bun-sqlite": "^0.3.2", | ||
"viem": "^2.21.53", | ||
"zod": "^3.23.8", | ||
"zod-openapi": "^4.2.3" | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Database as BunDatabase } from "bun:sqlite" | ||
import { Kysely } from "kysely" | ||
import { BunSqliteDialect } from "kysely-bun-sqlite" | ||
import type { Database } from "./types" | ||
|
||
import { env } from "../env" | ||
|
||
const dbPath = env.LEADERBOARD_DB_URL || ":memory:" | ||
|
||
export const db = new Kysely<Database>({ | ||
dialect: new BunSqliteDialect({ database: new BunDatabase(dbPath) }), | ||
GabrielMartinezRodriguez marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Add plugins here if needed | ||
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { type Migration, type MigrationProvider, Migrator } from "kysely" | ||
import { db } from "./driver" | ||
import { migrations } from "./migrations" | ||
|
||
class ObjectMigrationProvider implements MigrationProvider { | ||
constructor(private migrations: Record<string, Migration>) {} | ||
async getMigrations(): Promise<Record<string, Migration>> { | ||
return this.migrations | ||
} | ||
} | ||
|
||
const migrator = new Migrator({ | ||
db, | ||
provider: new ObjectMigrationProvider(migrations), | ||
}) | ||
|
||
async function migrateToLatest() { | ||
const { error, results } = await migrator.migrateToLatest() | ||
|
||
results?.forEach((it) => { | ||
if (it.status === "Success") { | ||
console.log(`migration "${it.migrationName}" was executed successfully`) | ||
} else if (it.status === "Error") { | ||
console.error(`failed to execute migration "${it.migrationName}"`) | ||
} | ||
}) | ||
|
||
if (error) { | ||
console.error("failed to migrate") | ||
console.error(error) | ||
process.exit(1) | ||
} | ||
|
||
await db.destroy() | ||
} | ||
|
||
migrateToLatest() |
89 changes: 89 additions & 0 deletions
89
apps/leaderboard-backend/src/db/migrations/1745907000000_create_all_tables.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import type { Kysely } from "kysely" | ||
import { sql } from "kysely" | ||
|
||
// biome-ignore lint/suspicious/noExplicitAny: `any` is required here since migrations should be frozen in time. alternatively, keep a "snapshot" db interface. | ||
export async function up(db: Kysely<any>): Promise<void> { | ||
// Users table | ||
await db.schema | ||
.createTable("users") | ||
.addColumn("id", "integer", (col) => col.primaryKey().autoIncrement()) | ||
.addColumn("primary_wallet", "text", (col) => col.notNull().unique()) | ||
.addColumn("username", "text", (col) => col.notNull().unique()) | ||
.addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()) | ||
.addColumn("updated_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()) | ||
.execute() | ||
|
||
// User wallets table (multiple wallets per user) | ||
await db.schema | ||
.createTable("user_wallets") | ||
.addColumn("id", "integer", (col) => col.primaryKey().autoIncrement()) | ||
.addColumn("user_id", "integer", (col) => col.notNull()) | ||
.addColumn("wallet_address", "text", (col) => col.notNull().unique()) | ||
.addColumn("is_primary", "boolean", (col) => col.notNull().defaultTo(false)) | ||
.addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()) | ||
.addForeignKeyConstraint("user_wallets_user_id_fk", ["user_id"], "users", ["id"]) | ||
.execute() | ||
|
||
// Guilds table | ||
await db.schema | ||
.createTable("guilds") | ||
.addColumn("id", "integer", (col) => col.primaryKey().autoIncrement()) | ||
.addColumn("name", "text", (col) => col.notNull().unique()) | ||
.addColumn("icon_url", "text", (col) => col) | ||
.addColumn("creator_id", "integer", (col) => col.notNull()) | ||
.addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()) | ||
.addColumn("updated_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()) | ||
.addForeignKeyConstraint("guilds_creator_id_fk", ["creator_id"], "users", ["id"]) | ||
.execute() | ||
|
||
// Guild members table (many-to-many users <-> guilds) | ||
await db.schema | ||
.createTable("guild_members") | ||
.addColumn("id", "integer", (col) => col.primaryKey().autoIncrement()) | ||
.addColumn("guild_id", "integer", (col) => col.notNull()) | ||
.addColumn("user_id", "integer", (col) => col.notNull()) | ||
.addColumn("is_admin", "boolean", (col) => col.notNull().defaultTo(false)) | ||
.addColumn("joined_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()) | ||
.addForeignKeyConstraint("guild_members_guild_id_fk", ["guild_id"], "guilds", ["id"]) | ||
.addForeignKeyConstraint("guild_members_user_id_fk", ["user_id"], "users", ["id"]) | ||
.addUniqueConstraint("guild_members_unique", ["guild_id", "user_id"]) | ||
.execute() | ||
|
||
// Games table | ||
await db.schema | ||
.createTable("games") | ||
.addColumn("id", "integer", (col) => col.primaryKey().autoIncrement()) | ||
.addColumn("name", "text", (col) => col.notNull().unique()) | ||
.addColumn("icon_url", "text", (col) => col) | ||
.addColumn("description", "text", (col) => col) | ||
.addColumn("admin_id", "integer", (col) => col.notNull()) | ||
.addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()) | ||
.addColumn("updated_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()) | ||
.addForeignKeyConstraint("games_admin_id_fk", ["admin_id"], "users", ["id"]) | ||
.execute() | ||
|
||
// User game scores table | ||
await db.schema | ||
.createTable("user_game_scores") | ||
.addColumn("id", "integer", (col) => col.primaryKey().autoIncrement()) | ||
.addColumn("user_id", "integer", (col) => col.notNull()) | ||
.addColumn("game_id", "integer", (col) => col.notNull()) | ||
.addColumn("score", "integer", (col) => col.notNull()) | ||
.addColumn("metadata", "text", (col) => col) | ||
.addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()) | ||
.addColumn("updated_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()) | ||
.addForeignKeyConstraint("user_game_scores_user_id_fk", ["user_id"], "users", ["id"]) | ||
.addForeignKeyConstraint("user_game_scores_game_id_fk", ["game_id"], "games", ["id"]) | ||
.addUniqueConstraint("user_game_scores_unique", ["user_id", "game_id"]) | ||
.execute() | ||
} | ||
|
||
// biome-ignore lint/suspicious/noExplicitAny: `any` is required here since migrations should be frozen in time. alternatively, keep a "snapshot" db interface. | ||
export async function down(db: Kysely<any>): Promise<void> { | ||
await db.schema.dropTable("user_game_scores").execute() | ||
await db.schema.dropTable("games").execute() | ||
await db.schema.dropTable("guild_members").execute() | ||
await db.schema.dropTable("guilds").execute() | ||
await db.schema.dropTable("user_wallets").execute() | ||
await db.schema.dropTable("users").execute() | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import * as M_1745907000000_create_all_tables from "./1745907000000_create_all_tables" | ||
|
||
export const migrations = { | ||
"1745907000000_create_all_tables": M_1745907000000_create_all_tables, | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.