Files
worldcup/lib/graphql/schema.ts
T
valknar 58b4114159 feat: initial commit — World Cup stats app with pnpm, Traefik, Docker
Full-stack World Cup web app (1930–2026):
- Next.js 16 + TailwindCSS 4 + GraphQL Yoga + Apollo Client 4 + Drizzle + PostgreSQL 16
- 23 tournaments synced from openfootball/worldcup.json (matches, goals, teams, stadiums, squads, standings)
- Pages: home (live), groups, stats, history, search, /tournaments/[year], /teams/[slug], /players/[name]
- Live match detection via isLive() + Apollo 60 s poll
- pnpm with node-linker=hoisted for Docker compatibility
- docker-compose.yml with Traefik labels (HTTPS redirect, TLS, security middleware)
- docker-compose.dev.yml for local dev (DB only, port 5432 exposed)
- Dockerfile: multi-stage pnpm build, standalone Next.js output, sync script bundled
- .env.example with all required variables documented
- Comprehensive README with local dev, deployment, schema, and GraphQL API reference

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 15:36:44 +02:00

200 lines
3.7 KiB
TypeScript

export const typeDefs = /* GraphQL */ `
type Tournament {
year: Int!
host: String!
winner: String
runnerUp: String
thirdPlace: String
fourthPlace: String
teamsCount: Int
matchesCount: Int
totalGoals: Int
avgGoalsPerGame: Float
topScorers: [ScorerEntry!]!
matches: [Match!]!
}
type Team {
id: Int!
name: String!
slug: String!
iso2: String
fifaCode: String
continent: String
confederation: String
stats: TeamStats
}
type TeamStats {
appearances: Int!
wins: Int!
draws: Int!
losses: Int!
goalsFor: Int!
goalsAgainst: Int!
goalDiff: Int!
titles: Int!
winPct: Float!
}
type Stadium {
id: Int!
tournamentYear: Int
name: String!
city: String
countryCode: String
capacity: Int
timezone: String
coordinates: String
matchCount: Int
}
type Match {
id: Int!
year: Int!
round: String!
group: String
date: String
time: String
stadium: String
team1: Team!
team2: Team!
scoreFt: [Int!]
scoreHt: [Int!]
scoreEt: [Int!]
scoreP: [Int!]
goals: [Goal!]!
isLive: Boolean!
isQualiPlayoff: Boolean!
margin: Int
totalGoals: Int
}
type Goal {
id: Int!
team: Team!
playerName: String!
minute: Int
minuteOffset: Int
isPenalty: Boolean!
isOwnGoal: Boolean!
}
type ScorerEntry {
playerName: String!
team: Team
goals: Int!
penalties: Int!
ownGoals: Int!
tournaments: Int!
}
type GroupStanding {
groupName: String!
pos: Int
team: Team!
played: Int!
won: Int!
drawn: Int!
lost: Int!
goalsFor: Int!
goalsAgainst: Int!
goalDiff: Int!
pts: Int!
}
type SquadPlayer {
playerName: String!
shirtNumber: Int
position: String
dateOfBirth: String
team: Team!
age: Int
}
type GlobalStats {
totalTournaments: Int!
totalMatches: Int!
totalGoals: Int!
avgGoalsPerGame: Float!
mostGoalsInTournament: TournamentGoalRecord
highestScoringMatch: Match
biggestWin: Match
mostTitles: ScorerEntry
}
type TournamentGoalRecord {
year: Int!
host: String!
totalGoals: Int!
}
type HatTrick {
playerName: String!
team: Team
year: Int!
round: String!
opponent: Team
goals: Int!
}
type MinuteBucket {
bucket: String!
count: Int!
}
type ConfederationStat {
confederation: String!
appearances: Int!
titles: Int!
totalGoals: Int!
}
type SearchResults {
tournaments: [Tournament!]!
teams: [Team!]!
players: [ScorerEntry!]!
matches: [Match!]!
}
type Query {
tournaments: [Tournament!]!
tournament(year: Int!): Tournament
matches(year: Int, group: String, round: String, isQuali: Boolean): [Match!]!
match(id: Int!): Match
liveMatches: [Match!]!
recentMatches(limit: Int): [Match!]!
upcomingMatches(limit: Int): [Match!]!
teams: [Team!]!
team(slug: String!): Team
topScorers(year: Int, limit: Int): [ScorerEntry!]!
player(name: String!): ScorerEntry
hatTricks(year: Int): [HatTrick!]!
groupStandings(year: Int!): [GroupStanding!]!
stadiums(year: Int): [Stadium!]!
squads(year: Int!, team: String): [SquadPlayer!]!
tournamentStats: GlobalStats!
goalsByMinute: [MinuteBucket!]!
confederationStats: [ConfederationStat!]!
biggestWins(limit: Int): [Match!]!
highestScoringMatches(limit: Int): [Match!]!
extraTimeStats: ExtraTimeStats!
search(query: String!): SearchResults!
}
type ExtraTimeStats {
totalKnockoutMatches: Int!
wentToExtraTime: Int!
wentToPenalties: Int!
extraTimePct: Float!
penaltiesPct: Float!
}
`