├── .eslintignore ├── .gitignore ├── .prettierrc ├── src ├── platform.ts ├── routes.ts ├── schemas.ts ├── api.ts └── models.ts ├── jest.config.js ├── examples ├── searchClub.ts ├── memberStats.ts ├── overallStats.ts ├── clubInfo.ts ├── memberCareerStats.ts └── matchesStats.ts ├── .eslintrc ├── tests ├── searchClub.test.ts ├── memberStats.test.ts ├── overallStats.test.ts └── matchesStats.test.ts ├── package.json ├── README.md └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "arrowParens": "avoid" 5 | } -------------------------------------------------------------------------------- /src/platform.ts: -------------------------------------------------------------------------------- 1 | export type TPlatform = 'common-gen5' | 'common-gen4' | 'nx' 2 | const PLATFORMS: TPlatform[] = ['common-gen5', 'common-gen4', 'nx'] 3 | 4 | export { PLATFORMS } 5 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | 3 | /** @type {import('ts-jest').JestConfigWithTsJest} */ 4 | module.exports = { 5 | preset: 'ts-jest', 6 | testEnvironment: 'node', 7 | } 8 | -------------------------------------------------------------------------------- /examples/searchClub.ts: -------------------------------------------------------------------------------- 1 | import { EAFCApiService } from '../src/api' 2 | 3 | const apiService = new EAFCApiService() 4 | const search = async () => 5 | apiService.searchClub({ 6 | clubName: 'PILOKA FC', 7 | platform: 'common-gen5', 8 | }) 9 | 10 | search().then(console.log).catch(console.error) 11 | -------------------------------------------------------------------------------- /examples/memberStats.ts: -------------------------------------------------------------------------------- 1 | import { EAFCApiService } from '../src/api' 2 | 3 | const apiService = new EAFCApiService() 4 | const memberStats = async () => 5 | apiService.memberStats({ 6 | clubId: '2605511', 7 | platform: 'common-gen5', 8 | }) 9 | 10 | memberStats().then(console.log).catch(console.error) 11 | -------------------------------------------------------------------------------- /examples/overallStats.ts: -------------------------------------------------------------------------------- 1 | import { EAFCApiService } from '../src/api' 2 | 3 | const apiService = new EAFCApiService() 4 | const overallStats = async () => 5 | apiService.overallStats({ 6 | clubIds: '2605511', 7 | platform: 'common-gen5', 8 | }) 9 | 10 | overallStats().then(console.log).catch(console.error) 11 | -------------------------------------------------------------------------------- /examples/clubInfo.ts: -------------------------------------------------------------------------------- 1 | import { EAFCApiService } from '../src/api' 2 | 3 | const apiService = new EAFCApiService() 4 | const search = async () => 5 | apiService.clubInfo({ 6 | clubIds: '2605511', 7 | platform: 'common-gen5', 8 | }) 9 | 10 | search() 11 | .then(c => console.log(c['2605511'])) 12 | .catch(console.error) 13 | -------------------------------------------------------------------------------- /examples/memberCareerStats.ts: -------------------------------------------------------------------------------- 1 | import { EAFCApiService } from '../src/api' 2 | 3 | const apiService = new EAFCApiService() 4 | const memberCareerStats = async () => 5 | apiService.memberCareerStats({ 6 | clubId: '2605511', 7 | platform: 'common-gen5', 8 | }) 9 | 10 | memberCareerStats().then(console.log).catch(console.error) 11 | -------------------------------------------------------------------------------- /examples/matchesStats.ts: -------------------------------------------------------------------------------- 1 | import { EAFCApiService } from '../src/api' 2 | 3 | const apiService = new EAFCApiService() 4 | const leagueMatchesStats = async () => 5 | apiService.matchesStats({ 6 | clubIds: '2605511', 7 | platform: 'common-gen5', 8 | matchType: 'playoffMatch', 9 | }) 10 | 11 | leagueMatchesStats().then(console.log).catch(console.error) 12 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "parserOptions": { 4 | "ecmaVersion": 12, 5 | "sourceType": "module" 6 | }, 7 | "plugins": ["@typescript-eslint"], 8 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], 9 | "rules": {}, 10 | "env": { 11 | "browser": true, 12 | "es2021": true 13 | }, 14 | "overrides": [ 15 | { 16 | "files": ["**/*.spec.js", "**/*.spec.jsx"], 17 | "env": { 18 | "jest": true 19 | } 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /tests/searchClub.test.ts: -------------------------------------------------------------------------------- 1 | import { EAFCApiService } from '../src/api' 2 | 3 | describe('EAFCApiService', () => { 4 | const apiService = new EAFCApiService() 5 | 6 | describe('searchClub', () => { 7 | it('should return an array of clubs', async () => { 8 | const result = await apiService.searchClub({ 9 | clubName: 'PILOKA FC', 10 | platform: 'common-gen5', 11 | }) 12 | expect(Array.isArray(result)).toBe(true) 13 | expect(result.length).toBeGreaterThan(0) 14 | }) 15 | 16 | it('should throw an error if the input is invalid', async () => { 17 | await expect( 18 | apiService.searchClub({ clubName: '', platform: 'nx' }), 19 | ).rejects.toThrow() 20 | }) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /tests/memberStats.test.ts: -------------------------------------------------------------------------------- 1 | import { EAFCApiService } from '../src/api' 2 | 3 | describe('EAFCApiService', () => { 4 | const apiService = new EAFCApiService() 5 | 6 | describe('overallStats', () => { 7 | it('should return an array of overall stats', async () => { 8 | const result = await apiService.overallStats({ 9 | clubIds: '2605511', 10 | platform: 'common-gen5', 11 | }) 12 | expect(Array.isArray(result)).toBe(true) 13 | expect(result.length).toBeGreaterThan(0) 14 | }) 15 | 16 | it('should throw an error if the input is invalid', async () => { 17 | await expect( 18 | apiService.overallStats({ clubIds: '', platform: 'common-gen5' }), 19 | ).rejects.toThrow() 20 | }) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /tests/overallStats.test.ts: -------------------------------------------------------------------------------- 1 | import { EAFCApiService } from '../src/api' 2 | 3 | describe('EAFCApiService', () => { 4 | const apiService = new EAFCApiService() 5 | 6 | describe('memberStats', () => { 7 | it('should return an array of member stats', async () => { 8 | const result = await apiService.memberStats({ 9 | clubId: '2605511', 10 | platform: 'common-gen5', 11 | }) 12 | expect(result).toHaveProperty('members') 13 | expect(result).toHaveProperty('positionCount') 14 | }) 15 | 16 | it('should throw an error if the input is invalid', async () => { 17 | await expect( 18 | apiService.memberStats({ clubId: '', platform: 'common-gen5' }), 19 | ).rejects.toThrow() 20 | }) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /src/routes.ts: -------------------------------------------------------------------------------- 1 | import { type AnyObjectSchema } from 'yup' 2 | import { SCHEMAS } from './schemas' 3 | 4 | type TRouteName = 5 | | 'CLUB_SEARCH' 6 | | 'OVERALL_STATS' 7 | | 'MEMBER_CAREER_STATS' 8 | | 'MEMBER_STATS' 9 | | 'MATCHES_STATS' 10 | | 'CLUB_INFO' 11 | 12 | interface ROUTE { 13 | url: string 14 | schema: AnyObjectSchema 15 | } 16 | 17 | const ROUTES: Record = { 18 | CLUB_SEARCH: { 19 | url: 'allTimeLeaderboard/search', 20 | schema: SCHEMAS.CLUB_SEARCH, 21 | }, 22 | OVERALL_STATS: { 23 | url: 'clubs/overallStats', 24 | schema: SCHEMAS.OVERALL_STATS, 25 | }, 26 | MEMBER_CAREER_STATS: { 27 | url: 'members/career/stats', 28 | schema: SCHEMAS.MEMBER_CAREER_STATS, 29 | }, 30 | MEMBER_STATS: { 31 | url: 'members/stats', 32 | schema: SCHEMAS.MEMBER_STATS, 33 | }, 34 | MATCHES_STATS: { 35 | url: 'clubs/matches', 36 | schema: SCHEMAS.MATCHES_STATS, 37 | }, 38 | CLUB_INFO: { 39 | url: 'clubs/info', 40 | schema: SCHEMAS.CLUB_INFO, 41 | }, 42 | } 43 | 44 | export type { TRouteName } 45 | export { ROUTES } 46 | -------------------------------------------------------------------------------- /tests/matchesStats.test.ts: -------------------------------------------------------------------------------- 1 | import { EAFCApiService } from '../src/api' 2 | 3 | describe('EAFCApiService', () => { 4 | const apiService = new EAFCApiService() 5 | 6 | describe('leagueMatchesStats', () => { 7 | it('should return an array of league matches stats', async () => { 8 | const result = await apiService.matchesStats({ 9 | clubIds: '2605511', 10 | platform: 'common-gen5', 11 | matchType: 'leagueMatch', 12 | }) 13 | expect(Array.isArray(result)).toBe(true) 14 | }) 15 | 16 | it('should return an array of playoff matches stats', async () => { 17 | const result = await apiService.matchesStats({ 18 | clubIds: '2605511', 19 | platform: 'common-gen5', 20 | matchType: 'playoffMatch', 21 | }) 22 | expect(Array.isArray(result)).toBe(true) 23 | }) 24 | 25 | it('should throw an error if the input is invalid', async () => { 26 | await expect( 27 | apiService.matchesStats({ 28 | clubIds: '', 29 | platform: 'nx', 30 | matchType: 'playoffMatch', 31 | }), 32 | ).rejects.toThrow() 33 | }) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eafc-clubs-api", 3 | "version": "1.2.0", 4 | "description": "", 5 | "main": "lib/api.js", 6 | "types": "lib/api.d.ts", 7 | "scripts": { 8 | "test": "jest", 9 | "build": "tsc", 10 | "lint": "eslint --ignore-path .eslintignore --ext .js,.ts .", 11 | "format": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\"", 12 | "prepare": "npm run build", 13 | "prepublishOnly": "npm test && npm run lint", 14 | "preversion": "npm run lint", 15 | "version": "npm run format && git add -A src", 16 | "postversion": "git push && git push --tags" 17 | }, 18 | "keywords": [ 19 | "eafc", 20 | "proclubs", 21 | "api" 22 | ], 23 | "author": "", 24 | "license": "ISC", 25 | "devDependencies": { 26 | "@types/jest": "^29.5.6", 27 | "@typescript-eslint/eslint-plugin": "^6.8.0", 28 | "eslint": "^8.52.0", 29 | "eslint-config-prettier": "^9.0.0", 30 | "eslint-config-standard-with-typescript": "^39.1.1", 31 | "eslint-plugin-import": "^2.28.1", 32 | "eslint-plugin-n": "^16.2.0", 33 | "eslint-plugin-promise": "^6.1.1", 34 | "jest": "^29.7.0", 35 | "prettier": "^3.0.3", 36 | "ts-jest": "^29.1.1", 37 | "typescript": "^5.2.2" 38 | }, 39 | "dependencies": { 40 | "yup": "^1.3.2" 41 | }, 42 | "files": [ 43 | "lib/**/*" 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /src/schemas.ts: -------------------------------------------------------------------------------- 1 | import { InferType, object, string } from 'yup' 2 | import { PLATFORMS } from './platform' 3 | 4 | export type TMatchType = 'leagueMatch' | 'playoffMatch' 5 | const MATCH_TYPES: TMatchType[] = ['leagueMatch', 'playoffMatch'] 6 | 7 | const SCHEMAS = { 8 | CLUB_SEARCH: object({ 9 | clubName: string().required().min(1).max(32), 10 | platform: string().required().oneOf(PLATFORMS), 11 | }), 12 | OVERALL_STATS: object({ 13 | clubIds: string().required(), 14 | platform: string().required().oneOf(PLATFORMS), 15 | }), 16 | MEMBER_CAREER_STATS: object({ 17 | clubId: string().required(), 18 | platform: string().required().oneOf(PLATFORMS), 19 | }), 20 | MEMBER_STATS: object({ 21 | clubId: string().required(), 22 | platform: string().required().oneOf(PLATFORMS), 23 | }), 24 | MATCHES_STATS: object({ 25 | clubIds: string().required(), 26 | platform: string().required().oneOf(PLATFORMS), 27 | matchType: string().required().oneOf(MATCH_TYPES), 28 | }), 29 | CLUB_INFO: object({ 30 | clubIds: string().required(), 31 | platform: string().required().oneOf(PLATFORMS), 32 | }), 33 | } as const 34 | 35 | type ClubSearchInput = InferType 36 | type OverallStatsInput = InferType 37 | type MemberCareerStatsInput = InferType 38 | type MemberStatsInput = InferType 39 | type MatchesStatsInput = InferType 40 | type ClubInfoInput = InferType 41 | 42 | export { SCHEMAS } 43 | export type { 44 | ClubSearchInput, 45 | OverallStatsInput, 46 | MemberCareerStatsInput, 47 | MemberStatsInput, 48 | MatchesStatsInput, 49 | ClubInfoInput, 50 | } 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # eafc-clubs-api 2 | 3 | An API written in TypeScript for the FC24 Clubs mode which allows developers to retrieve game statistics for all platforms. 4 | 5 | ## Installation 6 | `npm i eafc-clubs-api` 7 | 8 | ## Example 9 | Check `examples/` for common use cases of this library. 10 | 11 | ## Endpoints 12 | 13 | ### `searchClub(input: InferType): Promise` 14 | 15 | Search for a club by name. 16 | 17 | #### Parameters 18 | 19 | - `input`: An object containing the search parameters. The object must conform to the `SCHEMAS.CLUB_SEARCH` schema. 20 | 21 | #### Returns 22 | 23 | An array of `Club` objects that match the search criteria. 24 | 25 | ### `overallStats(input: InferType): Promise` 26 | 27 | Get the overall stats of the club. 28 | 29 | #### Parameters 30 | 31 | - `input`: An object containing the search parameters. The object must conform to the `SCHEMAS.OVERALL_STATS` schema. 32 | 33 | #### Returns 34 | 35 | An array of `OverallStats` objects that represent the overall stats of the club. 36 | 37 | ### `memberCareerStats(input: InferType): Promise` 38 | 39 | Get the stats of all members of the club. 40 | 41 | #### Parameters 42 | 43 | - `input`: An object containing the search parameters. The object must conform to the `SCHEMAS.MEMBER_CAREER_STATS` schema. 44 | 45 | #### Returns 46 | 47 | An array of `MemberCareerStats` objects that represent the career stats of all members of the club. 48 | 49 | ### `matchesStats(input: InferType): Promise` 50 | 51 | Get the stats of all matches of the club 52 | 53 | #### Parameters 54 | 55 | - `input`: An object containing the search parameters. The object must conform to the `SCHEMAS.MATCHES_STATS` schema. 56 | 57 | #### Returns 58 | 59 | An array of `Match` objects that represent the stats of all matches of the club. 60 | 61 | ### `memberStats(input: InferType): Promise` 62 | 63 | Get the stats of all members of the club. 64 | 65 | #### Parameters 66 | 67 | - `input`: An object containing the search parameters. The object must conform to the `SCHEMAS.MEMBER__STATS` schema. 68 | 69 | #### Returns 70 | 71 | An array of `MemberStats` objects that represent the stats of all members of the club. -------------------------------------------------------------------------------- /src/api.ts: -------------------------------------------------------------------------------- 1 | import type { InferType } from 'yup' 2 | import type { 3 | Club, 4 | ClubInfo, 5 | Match, 6 | MemberCareerStats, 7 | MemberStats, 8 | OverallStats, 9 | } from './models' 10 | import { ROUTES } from './routes' 11 | import type { 12 | ClubInfoInput, 13 | ClubSearchInput, 14 | MatchesStatsInput, 15 | MemberCareerStatsInput, 16 | MemberStatsInput, 17 | OverallStatsInput, 18 | } from './schemas' 19 | import { SCHEMAS } from './schemas' 20 | 21 | class EAFCApiService { 22 | private readonly baseUrl = new URL('https://proclubs.ea.com/api/fc/') 23 | 24 | /** 25 | * Send a GET request to the EAFC API 26 | * 27 | * @param endpoint 28 | * @returns 29 | */ 30 | private get = async , TModel>( 31 | endpoint: keyof typeof ROUTES, 32 | input: TInput, 33 | ): Promise => { 34 | const route = ROUTES[endpoint] 35 | const url = new URL(route.url, this.baseUrl) 36 | await route.schema.validate(input, { strict: true }) 37 | Object.keys(input).forEach(key => { 38 | url.searchParams.append(key, input[key]) 39 | }) 40 | 41 | const response = await fetch(url.toString(), { 42 | headers: { 43 | 'User-Agent': 44 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/112.0', 45 | Accept: 46 | 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 47 | 'Accept-Encoding': 'gzip, deflate, br', 48 | }, 49 | method: 'GET', 50 | }) 51 | const json: TModel = await response.json() 52 | return json 53 | } 54 | 55 | /** 56 | * Search for a club by name 57 | * @param input 58 | * @returns 59 | */ 60 | searchClub = async ( 61 | input: InferType, 62 | ): Promise => this.get('CLUB_SEARCH', input) 63 | 64 | /** 65 | * Get the overall stats of the club 66 | * @param input 67 | * @returns 68 | */ 69 | overallStats = async ( 70 | input: InferType, 71 | ): Promise => this.get('OVERALL_STATS', input) 72 | 73 | /** 74 | * Get the career stats of all members of the club 75 | * @param input 76 | * @returns 77 | */ 78 | memberCareerStats = async ( 79 | input: InferType, 80 | ): Promise => this.get('MEMBER_CAREER_STATS', input) 81 | 82 | /** 83 | * Get the career stats of all members of the club 84 | * @param input 85 | * @returns 86 | */ 87 | memberStats = async ( 88 | input: InferType, 89 | ): Promise => this.get('MEMBER_STATS', input) 90 | 91 | /** 92 | * Get the stats of all matches of the club 93 | * @param input 94 | * @returns 95 | */ 96 | matchesStats = async ( 97 | input: InferType, 98 | ): Promise => this.get('MATCHES_STATS', input) 99 | 100 | /** 101 | * Gets information of a club 102 | * Note that you need to index the response by the `clubId`, e.g. check `examples/clubInfo` 103 | * 104 | * @param input 105 | * @returns 106 | */ 107 | clubInfo = async ( 108 | input: InferType, 109 | ): Promise => this.get('CLUB_INFO', input) 110 | } 111 | 112 | export { EAFCApiService, SCHEMAS } 113 | export type { 114 | Club, 115 | ClubInfo, 116 | ClubInfoInput, 117 | ClubSearchInput, 118 | Match, 119 | MatchesStatsInput, 120 | MemberCareerStats, 121 | MemberCareerStatsInput, 122 | MemberStats, 123 | MemberStatsInput, 124 | OverallStats, 125 | OverallStatsInput, 126 | } 127 | -------------------------------------------------------------------------------- /src/models.ts: -------------------------------------------------------------------------------- 1 | export interface Club { 2 | clubId: string 3 | wins: string 4 | losses: string 5 | ties: string 6 | gamesPlayed: string 7 | gamesPlayedPlayoff: string 8 | goals: string 9 | goalsAgainst: string 10 | cleanSheets: string 11 | points: string 12 | reputationtier: string 13 | clubInfo: ClubInfo[keyof ClubInfo] 14 | platform: string 15 | clubName: string 16 | currentDivision: string 17 | } 18 | 19 | /** 20 | * Here, the key is the `clubId` 21 | */ 22 | export type ClubInfo = Record< 23 | string, 24 | { 25 | name: string 26 | clubId: number 27 | regionId: number 28 | teamId: number 29 | customKit: { 30 | stadName: string 31 | kitId: string 32 | seasonalTeamId: string 33 | seasonalKitId: string 34 | selectedKitType: string 35 | customKitId: string 36 | customAwayKitId: string 37 | customThirdKitId: string 38 | customKeeperKitId: string 39 | kitColor1: string 40 | kitColor2: string 41 | kitColor3: string 42 | kitColor4: string 43 | kitAColor1: string 44 | kitAColor2: string 45 | kitAColor3: string 46 | kitAColor4: string 47 | kitThrdColor1: string 48 | kitThrdColor2: string 49 | kitThrdColor3: string 50 | kitThrdColor4: string 51 | dCustomKit: string 52 | crestColor: string 53 | crestAssetId: string 54 | } 55 | } 56 | > 57 | 58 | export interface OverallStats { 59 | clubId: string 60 | bestDivision: string 61 | bestFinishGroup: string 62 | finishesInDivision1Group1: string 63 | finishesInDivision2Group1: string 64 | finishesInDivision3Group1: string 65 | finishesInDivision4Group1: string 66 | finishesInDivision5Group1: string 67 | finishesInDivision6Group1: string 68 | gamesPlayed: string 69 | gamesPlayedPlayoff: string 70 | goals: string 71 | goalsAgainst: string 72 | promotions: string 73 | relegations: string 74 | losses: string 75 | ties: string 76 | wins: string 77 | lastMatch0: string 78 | lastMatch1: string 79 | lastMatch2: string 80 | lastMatch3: string 81 | lastMatch4: string 82 | lastMatch5: string 83 | lastMatch6: string 84 | lastMatch7: string 85 | lastMatch8: string 86 | lastMatch9: string 87 | lastOpponent0: string 88 | lastOpponent1: string 89 | lastOpponent2: string 90 | lastOpponent3: string 91 | lastOpponent4: string 92 | lastOpponent5: string 93 | lastOpponent6: string 94 | lastOpponent7: string 95 | lastOpponent8: string 96 | lastOpponent9: string 97 | wstreak: string 98 | unbeatenstreak: string 99 | skillRating: string 100 | reputationtier: string 101 | leagueAppearances: string 102 | } 103 | 104 | export interface MemberCareerStats { 105 | members: Array<{ 106 | name: string 107 | proPos: string 108 | gamesPlayed: string 109 | goals: string 110 | assists: string 111 | manOfTheMatch: string 112 | ratingAve: string 113 | prevGoals: string 114 | favoritePosition: string 115 | }> 116 | positionCount: { 117 | midfielder: number 118 | goalkeeper: number 119 | forward: number 120 | defender: number 121 | } 122 | } 123 | 124 | export interface Match { 125 | matchId: string 126 | timestamp: number 127 | timeAgo: { 128 | number: number 129 | unit: string 130 | } 131 | clubs: Record< 132 | string, 133 | { 134 | date: string 135 | gameNumber: string 136 | goals: string 137 | goalsAgainst: string 138 | losses: string 139 | matchType: string 140 | result: string 141 | score: string 142 | season_id: string 143 | TEAM: string 144 | ties: string 145 | winnerByDnf: string 146 | wins: string 147 | details: { 148 | name: string 149 | clubId: number 150 | regionId: number 151 | teamId: number 152 | customKit: { 153 | stadName: string 154 | kitId: string 155 | seasonalTeamId: string 156 | seasonalKitId: string 157 | selectedKitType: string 158 | customKitId: string 159 | customAwayKitId: string 160 | customThirdKitId: string 161 | customKeeperKitId: string 162 | kitColor1: string 163 | kitColor2: string 164 | kitColor3: string 165 | kitColor4: string 166 | kitAColor1: string 167 | kitAColor2: string 168 | kitAColor3: string 169 | kitAColor4: string 170 | kitThrdColor1: string 171 | kitThrdColor2: string 172 | kitThrdColor3: string 173 | kitThrdColor4: string 174 | dCustomKit: string 175 | crestColor: string 176 | crestAssetId: string 177 | } 178 | } 179 | } 180 | > 181 | players: Record< 182 | string, 183 | Record< 184 | string, 185 | { 186 | assists: string 187 | cleansheetsany: string 188 | cleansheetsdef: string 189 | cleansheetsgk: string 190 | goals: string 191 | goalsconceded: string 192 | losses: string 193 | mom: string 194 | namespace: string 195 | passattempts: string 196 | passesmade: string 197 | pos: string 198 | rating: string 199 | realtimegame: string 200 | realtimeidle: string 201 | redcards: string 202 | saves: string 203 | SCORE: string 204 | shots: string 205 | tackleattempts: string 206 | tacklesmade: string 207 | vproattr: string 208 | vprohackreason: string 209 | wins: string 210 | playername: string 211 | } 212 | > 213 | > 214 | aggregate: Record< 215 | string, 216 | { 217 | assists: number 218 | cleansheetsany: number 219 | cleansheetsdef: number 220 | cleansheetsgk: number 221 | goals: number 222 | goalsconceded: number 223 | losses: number 224 | mom: number 225 | namespace: number 226 | passattempts: number 227 | passesmade: number 228 | pos: number 229 | rating: number 230 | realtimegame: number 231 | realtimeidle: number 232 | redcards: number 233 | saves: number 234 | SCORE: number 235 | shots: number 236 | tackleattempts: number 237 | tacklesmade: number 238 | vproattr: number 239 | vprohackreason: number 240 | wins: number 241 | } 242 | > 243 | } 244 | 245 | export type MemberStats = { 246 | members: Array<{ 247 | name: string 248 | gamesPlayed: string 249 | winRate: string 250 | goals: string 251 | assists: string 252 | cleanSheetsDef: string 253 | cleanSheetsGK: string 254 | shotSuccessRate: string 255 | passesMade: string 256 | passSuccessRate: string 257 | ratingAve: string 258 | tacklesMade: string 259 | tackleSuccessRate: string 260 | proName: string 261 | proPos: string 262 | proStyle: string 263 | proHeight: string 264 | proNationality: string 265 | proOverall: string 266 | manOfTheMatch: string 267 | redCards: string 268 | prevGoals: string 269 | prevGoals1: string 270 | prevGoals2: string 271 | prevGoals3: string 272 | prevGoals4: string 273 | prevGoals5: string 274 | prevGoals6: string 275 | prevGoals7: string 276 | prevGoals8: string 277 | prevGoals9: string 278 | prevGoals10: string 279 | favoritePosition: string 280 | }> 281 | positionCount: { 282 | midfielder: number 283 | goalkeeper: number 284 | forward: number 285 | defender: number 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "exclude": ["node_modules", "tests"], 4 | "compilerOptions": { 5 | /* Visit https://aka.ms/tsconfig to read more about this file */ 6 | 7 | /* Projects */ 8 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 9 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 10 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 11 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 12 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 13 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 14 | 15 | /* Language and Environment */ 16 | "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, 17 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 18 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 19 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 20 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 21 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 22 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 23 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 24 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 25 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 26 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 27 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 28 | 29 | /* Modules */ 30 | "module": "commonjs" /* Specify what module code is generated. */, 31 | // "rootDir": "./", /* Specify the root folder within your source files. */ 32 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ 33 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 34 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 35 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 36 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 37 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 38 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 39 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 40 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 41 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 42 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 43 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 44 | // "resolveJsonModule": true, /* Enable importing .json files. */ 45 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 46 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 47 | 48 | /* JavaScript Support */ 49 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 50 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 51 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 52 | 53 | /* Emit */ 54 | "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, 55 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 56 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 57 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 59 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 60 | "outDir": "./lib" /* Specify an output folder for all emitted files. */, 61 | // "removeComments": true, /* Disable emitting comments. */ 62 | // "noEmit": true, /* Disable emitting files from a compilation. */ 63 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 64 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 65 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 66 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 67 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 68 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 69 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 70 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 71 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 72 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 73 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 74 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 75 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 76 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 77 | 78 | /* Interop Constraints */ 79 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 80 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 81 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 82 | "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, 83 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 84 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, 85 | 86 | /* Type Checking */ 87 | "strict": true /* Enable all strict type-checking options. */, 88 | "noImplicitAny": true /* Enable error reporting for expressions and declarations with an implied 'any' type. */, 89 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 90 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 91 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 92 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 93 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 94 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 95 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 96 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 97 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 98 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 99 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 100 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 101 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 102 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 103 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 104 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 105 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 106 | 107 | /* Completeness */ 108 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 109 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 110 | } 111 | } 112 | --------------------------------------------------------------------------------