This commit is contained in:
yohlo
2025-08-20 22:35:40 -05:00
commit f51c278cd3
169 changed files with 8173 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
import PocketBase from 'pocketbase';
import { createPlayersService } from './services/players';
import { createTournamentsService } from './services/tournaments';
import { createTeamsService } from './services/teams';
class PocketBaseAdminClient {
private pb: PocketBase;
private authPromise: Promise<void>;
constructor() {
this.pb = new PocketBase(import.meta.env.VITE_POCKETBASE_URL);
this.pb.beforeSend = (url, options) => {
options.cache = 'no-store';
options.headers = {
...options.headers,
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0'
};
return { url, options };
};
this.pb.autoCancellation(false);
this.authPromise = this.authenticate();
this.authPromise.then(() => {
Object.assign(this, createPlayersService(this.pb));
Object.assign(this, createTeamsService(this.pb));
Object.assign(this, createTournamentsService(this.pb));
});
}
private async authenticate() {
await this.pb.collection("_superusers").authWithPassword(
import.meta.env.VITE_POCKETBASE_ADMIN_EMAIL!,
import.meta.env.VITE_POCKETBASE_ADMIN_PASSWORD!
);
}
}
interface AdminClient extends
PocketBaseAdminClient,
ReturnType<typeof createPlayersService>,
ReturnType<typeof createTeamsService>,
ReturnType<typeof createTournamentsService> {}
export const pbAdmin = new PocketBaseAdminClient() as AdminClient;

View File

@@ -0,0 +1,46 @@
import type { Player, PlayerInput, PlayerUpdateInput } from '@/features/players/types';
import { transformPlayer } from '@/lib/pocketbase/util/transform-types';
import PocketBase from 'pocketbase';
export function createPlayersService(pb: PocketBase) {
return {
async getPlayerByAuthId(authId: string): Promise<Player | null> {
const result = await pb.collection('players').getList<Player>(1, 1, {
filter: `auth_id = "${authId}"`
});
return result.items[0] ? transformPlayer(result.items[0]) : null;
},
async getPlayer(id: string): Promise<Player | null> {
const result = await pb.collection('players').getOne(id, {
expand: 'teams'
});
return transformPlayer(result);
},
async listPlayers(): Promise<Player[]> {
const result = await pb.collection('players').getFullList<Player>({
fields: 'id,first_name,last_name'
});
return result.map(transformPlayer);
},
async createPlayer(data: PlayerInput): Promise<Player> {
const result = await pb.collection('players').create<Player>(data);
return transformPlayer(result);
},
async updatePlayer(id: string, data: PlayerUpdateInput): Promise<Player> {
const result = await pb.collection('players').update<Player>(id, data);
return transformPlayer(result);
},
async getUnassociatedPlayers(): Promise<Player[]> {
const result = await pb.collection('players').getFullList<Player>({
filter: 'auth_id = ""',
fields: 'id,first_name,last_name'
});
return result.map(transformPlayer);
}
};
}

View File

@@ -0,0 +1,20 @@
import { logger } from "@/lib/logger";
import PocketBase from "pocketbase";
import { transformTeam } from "@/lib/pocketbase/util/transform-types";
import { Team } from "@/features/teams/types";
export function createTeamsService(pb: PocketBase) {
return {
async getTeam(id: string): Promise<Team | null> {
try {
logger.info('PocketBase | Getting team', id);
const result = await pb.collection('teams').getOne(id, {
expand: 'players, tournaments'
});
return transformTeam(result);
} catch {
return null;
}
},
};
}

View File

@@ -0,0 +1,57 @@
import { logger } from "@/lib/logger";
import type { Tournament, TournamentInput, TournamentUpdateInput } from "@/features/tournaments/types";
import PocketBase from "pocketbase";
import { transformTournament } from "@/lib/pocketbase/util/transform-types";
import { BracketGenerator } from "@/features/bracket/bracket";
export function createTournamentsService(pb: PocketBase) {
return {
async getTournament(id: string): Promise<Tournament | null> {
try {
const generator = new BracketGenerator(12, true);
console.log("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-")
console.log('Winners Bracket:');
generator.bracket.forEach((round, i) => {
console.log(`Round ${i}:`);
round.forEach(match => {
console.log('-', match);
});
});
console.log('\nLosers Bracket:');
generator.losersBracket.forEach((round, i) => {
console.log(`Round ${i}:`);
round.forEach(match => {
console.log('-', match);
});
});
logger.info('PocketBase | Getting tournament', id);
const result = await pb.collection('tournaments').getOne(id, {
expand: 'teams, teams.players'
});
return transformTournament(result);
} catch {
return null;
}
},
async listTournaments(): Promise<Tournament[]> {
const result = await pb.collection('tournaments').getFullList<Tournament>({
fields: 'id,name,start_time,end_time,logo_url,created',
sort: '-created'
});
console.log(result)
return result.map(transformTournament);
},
async createTournament(data: TournamentInput): Promise<Tournament> {
const result = await pb.collection('tournaments').create<Tournament>(data);
return transformTournament(result);
},
async updateTournament(id: string, data: TournamentUpdateInput): Promise<Tournament> {
const result = await pb.collection('tournaments').update<Tournament>(id, data);
return transformTournament(result);
},
};
}

View File

@@ -0,0 +1,69 @@
import { Player } from "@/features/players/types";
import { Team } from "@/features/teams/types";
import { Tournament } from "@/features/tournaments/types";
// pocketbase does this weird thing with relations where it puts them under a seperate "expand" field
// this file transforms raw pocketbase results to our types
export function transformPlayer(record: any): Player {
const sadf: string[] = [];
const teams = record.expand?.teams
?.sort((a: Team, b: Team) => new Date(a.created) < new Date(b.created) ? -1 : 0)
?.map(transformTeam) ?? [];
return {
id: record.id!,
first_name: record.first_name,
last_name: record.last_name,
auth_id: record.auth_id,
created: record.created,
updated: record.updated,
teams,
};
}
export function transformTeam(record: any): Team {
const players = record.expand?.players
?.sort((a: Player, b: Player) => new Date(a.created!) < new Date(b.created!) ? -1 : 0)
?.map(transformPlayer) ?? [];
return {
id: record.id,
name: record.name,
logo_url: record.logo_url,
primary_color: record.primary_color,
accent_color: record.accent_color,
song_id: record.song_id,
song_name: record.song_name,
song_artist: record.song_artist,
song_album: record.song_album,
song_year: record.song_year,
song_start: record.song_start,
song_end: 0,
song_image_url: record.song_image_url,
created: record.created,
updated: record.updated,
players,
};
}
export function transformTournament(record: any): Tournament {
const teams = record.expand?.teams
?.sort((a: Team, b: Team) => new Date(a.created) < new Date(b.created) ? -1 : 0)
?.map(transformTeam) ?? [];
return {
id: record.id,
name: record.name,
location: record.location,
desc: record.desc,
rules: record.rules,
logo_url: record.logo_url,
enroll_time: record.enroll_time,
start_time: record.start_time,
end_time: record.end_time,
created: record.created,
updated: record.updated,
teams,
};
}