import {z} from 'zod' export type ValorantAffinity = 'na' | 'eu' | 'ap' | 'kr' | 'br' | 'latam'; export type GetApiValorantV3ByPuuidMatchesAffinityPuuidArgs = {affinity: ValorantAffinity, puuid: string, mode?: string | undefined, queue?: string | undefined, map?: string | undefined, size?: number | undefined}; export type GetApiValorantV3ByPuuidMatchesAffinityPuuidOptions = {baseUrl?: string | undefined, apiKeyHeader?: string | undefined, fetch?: typeof fetch | undefined}; export const matchesV2DataCoach = z.object({puuid: z.string(), team: z.string()}); export const matchesV2DataRoundPlayerStatsKillEventsAssistants = z.object({assistant_display_name: z.string(), assistant_puuid: z.string(), assistant_team: z.string()}); export const matchesV2DataRoundPlayerStatsKillEventsAssets = z.object({display_icon: z.string().nullable().optional(), killfeed_icon: z.string().nullable().optional()}); export const matchesV2DataRoundEventLocation = z.object({x: z.number().int(), y: z.number().int()}); export const matchesV2DataRoundPlayerLocationsOnEvent = z.object({location: matchesV2DataRoundEventLocation, player_display_name: z.string(), player_puuid: z.string(), player_team: z.string(), view_radians: z.number()}); export const matchesV2DataKill = z.object({assistants: z.array(matchesV2DataRoundPlayerStatsKillEventsAssistants), damage_weapon_assets: matchesV2DataRoundPlayerStatsKillEventsAssets, damage_weapon_id: z.string(), damage_weapon_name: z.string().nullable().optional(), kill_time_in_match: z.number().int().gte(0), kill_time_in_round: z.number().int().gte(0), killer_display_name: z.string(), killer_puuid: z.string(), killer_team: z.string(), player_locations_on_kill: z.array(matchesV2DataRoundPlayerLocationsOnEvent), round: z.number().int().gte(0), secondary_fire_mode: z.boolean(), victim_death_location: matchesV2DataRoundEventLocation, victim_display_name: z.string(), victim_puuid: z.string(), victim_team: z.string()}); export const matchesV2DataMetadataPremierInfo = z.object({matchup_id: z.string().nullable().optional(), tournament_id: z.string().nullable().optional()}); export const matchesV2DataMetadata = z.object({cluster: z.string().nullable().optional(), game_length: z.number().int().gte(0), game_start: z.number().int().gte(0), game_start_patched: z.string(), game_version: z.string(), map: z.string().nullable().optional(), matchid: z.string(), mode: z.string().nullable().optional(), mode_id: z.string(), platform: z.string(), premier_info: matchesV2DataMetadataPremierInfo, queue: z.string().nullable().optional(), region: z.string().nullable().optional(), rounds_played: z.number().int().gte(0), season_id: z.string()}); export const matchesV2DataPlatformOs = z.object({name: z.string(), version: z.string()}); export const matchesV2DataPlatform = z.object({os: matchesV2DataPlatformOs, type: z.string()}); export const matchesV2DataPlayerSessionPlaytime = z.object({milliseconds: z.number().int().gte(0), minutes: z.number().int().gte(0), seconds: z.number().int().gte(0)}); export const matchesV2DataObserver = z.object({level: z.number().int().gte(0), name: z.string(), party_id: z.string(), platform: matchesV2DataPlatform, player_card: z.string(), player_title: z.string(), puuid: z.string(), session_playtime: matchesV2DataPlayerSessionPlaytime, tag: z.string(), team: z.string()}); export const matchesV2DataPlayerAbilityCasts = z.object({c_cast: z.number().int().gte(0).nullable().optional(), e_cast: z.number().int().gte(0).nullable().optional(), q_cast: z.number().int().gte(0).nullable().optional(), x_cast: z.number().int().gte(0).nullable().optional()}); export const matchesV2DataPlayerAssetsAgent = z.object({bust: z.string(), full: z.string(), killfeed: z.string(), small: z.string()}); export const matchesV2DataPlayerAssetsCard = z.object({large: z.string(), small: z.string(), wide: z.string()}); export const matchesV2DataPlayerAssets = z.object({agent: matchesV2DataPlayerAssetsAgent, card: matchesV2DataPlayerAssetsCard}); export const matchesV2DataPlayerBehaviorFriendlyFire = z.object({incoming: z.number().nullable().optional(), outgoing: z.number().nullable().optional()}); export const matchesV2DataPlayerBehavior = z.object({afk_rounds: z.number(), friendly_fire: matchesV2DataPlayerBehaviorFriendlyFire, rounds_in_spawn: z.number().nullable().optional()}); export const matchesV2DataPlayerEconomyValue = z.object({average: z.number(), overall: z.number().int()}); export const matchesV2DataPlayerEconomy = z.object({loadout_value: matchesV2DataPlayerEconomyValue, spent: matchesV2DataPlayerEconomyValue}); export const matchesV2DataPlayerStats = z.object({assists: z.number().int().gte(0), bodyshots: z.number().int().gte(0), deaths: z.number().int().gte(0), headshots: z.number().int().gte(0), kills: z.number().int().gte(0), legshots: z.number().int().gte(0), score: z.number().int()}); export const matchesV2DataPlayer = z.object({ability_casts: matchesV2DataPlayerAbilityCasts, assets: matchesV2DataPlayerAssets, behavior: matchesV2DataPlayerBehavior, character: z.string().nullable().optional(), currenttier: z.number().int().gte(0), currenttier_patched: z.string(), damage_made: z.number().int(), damage_received: z.number().int(), economy: matchesV2DataPlayerEconomy, level: z.number().int().gte(0), name: z.string(), party_id: z.string(), platform: matchesV2DataPlatform, player_card: z.string(), player_title: z.string(), puuid: z.string(), session_playtime: matchesV2DataPlayerSessionPlaytime, stats: matchesV2DataPlayerStats, tag: z.string(), team: z.string()}); export const matchesV2DataPlayers = z.object({all_players: z.array(matchesV2DataPlayer), blue: z.array(matchesV2DataPlayer), red: z.array(matchesV2DataPlayer)}); export const matchesV2DataRoundPlayer = z.object({display_name: z.string(), puuid: z.string(), team: z.string()}); export const matchesV2DataRoundDefuseEvents = z.object({defuse_location: matchesV2DataRoundEventLocation.nullable().optional(), defuse_time_in_round: z.number().int().gte(0).nullable().optional(), defused_by: matchesV2DataRoundPlayer.nullable().optional(), player_locations_on_defuse: z.array(matchesV2DataRoundPlayerLocationsOnEvent).nullable().optional()}); export const matchesV2DataRoundPlantEvents = z.object({plant_location: matchesV2DataRoundEventLocation.nullable().optional(), plant_site: z.string().nullable().optional(), plant_time_in_round: z.number().int().gte(0).nullable().optional(), planted_by: matchesV2DataRoundPlayer.nullable().optional(), player_locations_on_plant: z.array(matchesV2DataRoundPlayerLocationsOnEvent).nullable().optional()}); export const matchesV2DataRoundPlayerStatsAbilityCasts = z.object({c_casts: z.number().int().gte(0).nullable().optional(), e_casts: z.number().int().gte(0).nullable().optional(), q_casts: z.number().int().gte(0).nullable().optional(), x_casts: z.number().int().gte(0).nullable().optional()}); export const matchesV2DataRoundPlayerStatsDamageEvents = z.object({bodyshots: z.number().int().gte(0), damage: z.number().int().gte(0), headshots: z.number().int().gte(0), legshots: z.number().int().gte(0), receiver_display_name: z.string(), receiver_puuid: z.string(), receiver_team: z.string()}); export const matchesV2DataRoundPlayerStatsEconomyEquipmentAssetsArmor = z.object({display_icon: z.string().nullable().optional()}); export const matchesV2DataRoundPlayerStatsEconomyEquipmentArmor = z.object({assets: matchesV2DataRoundPlayerStatsEconomyEquipmentAssetsArmor, id: z.string().nullable().optional(), name: z.string().nullable().optional()}); export const matchesV2DataRoundPlayerStatsEconomyEquipmentAssets = z.object({display_icon: z.string().nullable().optional(), killfeed_icon: z.string().nullable().optional()}); export const matchesV2DataRoundPlayerStatsEconomyEquipmentWeapon = z.object({assets: matchesV2DataRoundPlayerStatsEconomyEquipmentAssets, id: z.string().nullable().optional(), name: z.string().nullable().optional()}); export const matchesV2DataRoundPlayerStatsEconomy = z.object({armor: matchesV2DataRoundPlayerStatsEconomyEquipmentArmor, loadout_value: z.number().int().gte(0), remaining: z.number().int().gte(0), spent: z.number().int(), weapon: matchesV2DataRoundPlayerStatsEconomyEquipmentWeapon}); export const matchesV2DataRoundPlayerStatsKillEvents = z.object({assistants: z.array(matchesV2DataRoundPlayerStatsKillEventsAssistants), damage_weapon_assets: matchesV2DataRoundPlayerStatsKillEventsAssets, damage_weapon_id: z.string(), damage_weapon_name: z.string().nullable().optional(), kill_time_in_match: z.number().int().gte(0), kill_time_in_round: z.number().int().gte(0), killer_display_name: z.string(), killer_puuid: z.string(), killer_team: z.string(), player_locations_on_kill: z.array(matchesV2DataRoundPlayerLocationsOnEvent), secondary_fire_mode: z.boolean(), victim_death_location: matchesV2DataRoundEventLocation, victim_display_name: z.string(), victim_puuid: z.string(), victim_team: z.string()}); export const matchesV2DataRoundPlayerStats = z.object({ability_casts: matchesV2DataRoundPlayerStatsAbilityCasts, bodyshots: z.number().int().gte(0), damage: z.number().int().gte(0), damage_events: z.array(matchesV2DataRoundPlayerStatsDamageEvents), economy: matchesV2DataRoundPlayerStatsEconomy, headshots: z.number().int().gte(0), kill_events: z.array(matchesV2DataRoundPlayerStatsKillEvents), kills: z.number().int().gte(0), legshots: z.number().int().gte(0), player_display_name: z.string(), player_puuid: z.string(), player_team: z.string(), score: z.number().int(), stayed_in_spawn: z.boolean(), was_afk: z.boolean(), was_penalized: z.boolean()}); export const matchesV2DataRound = z.object({bomb_defused: z.boolean(), bomb_planted: z.boolean(), defuse_events: matchesV2DataRoundDefuseEvents, end_type: z.string(), plant_events: matchesV2DataRoundPlantEvents, player_stats: z.array(matchesV2DataRoundPlayerStats), winning_team: z.string()}); export const matchesV2DataTeamRosterCustomization = z.object({icon: z.string(), image: z.string(), primary_color: z.string(), secondary_color: z.string(), tertiary_color: z.string()}); export const matchesV2DataTeamRoster = z.object({customization: matchesV2DataTeamRosterCustomization, id: z.string(), members: z.array(z.string()), name: z.string(), tag: z.string()}); export const matchesV2DataTeam = z.object({has_won: z.boolean().nullable().optional(), roster: matchesV2DataTeamRoster.nullable().optional(), rounds_lost: z.number().int().gte(0).nullable().optional(), rounds_won: z.number().int().gte(0).nullable().optional()}); export const matchesV2DataTeams = z.object({blue: matchesV2DataTeam, red: matchesV2DataTeam}); export const matchesV3ListResponseData = z.object({coaches: z.array(matchesV2DataCoach), is_available: z.boolean(), kills: z.array(matchesV2DataKill), metadata: matchesV2DataMetadata.nullable().optional(), observers: z.array(matchesV2DataObserver), players: matchesV2DataPlayers.nullable().optional(), rounds: z.array(matchesV2DataRound), teams: matchesV2DataTeams.nullable().optional()}); export const matchesV3ListResponse = z.object({data: z.array(matchesV3ListResponseData), status: z.number().int().gte(0)}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Get matches by PUUID (v3) * * GET /valorant/v3/by-puuid/matches/{affinity}/{puuid} * * Also accepts auth: api_key_query */ export const getApiValorantV3ByPuuidMatchesAffinityPuuid = async (args: GetApiValorantV3ByPuuidMatchesAffinityPuuidArgs, options?: GetApiValorantV3ByPuuidMatchesAffinityPuuidOptions) => { const {baseUrl = "https://api.henrikdev.xyz", fetch: fetchFn = fetch, apiKeyHeader} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.mode != null) query.append("mode", String(args.mode)) if (args.queue != null) query.append("queue", String(args.queue)) if (args.map != null) query.append("map", String(args.map)) if (args.size != null) query.append("size", String(args.size)) if (apiKeyHeader !== undefined) headers.set("Authorization", apiKeyHeader) const url = `${baseUrl.replace(/\/+$/, '')}/valorant/v3/by-puuid/matches/${encodeURIComponent(String(args.affinity))}/${encodeURIComponent(String(args.puuid))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(matchesV3ListResponse, await res.json()) };