Skip to content

Instantly share code, notes, and snippets.

@harrisrobin
Created March 20, 2025 22:06
Show Gist options
  • Select an option

  • Save harrisrobin/4029dde42a6c63e23bca36d8225910c3 to your computer and use it in GitHub Desktop.

Select an option

Save harrisrobin/4029dde42a6c63e23bca36d8225910c3 to your computer and use it in GitHub Desktop.
syntax-highlighting-tests
/**
* This Api class lets you define an API endpoint and methods to request
* data and process it.
*/
import { ApisauceInstance, create } from 'apisauce'
import type {
ApiConfig,
CloudHeroSummaryParams,
CloudHeroSummaryRow,
CloutHeroQuickOverviewParams,
CloutHeroQuickOverviewResponse,
CloutResponse,
HeroFeedParams,
HeroFeedResponse,
HeroLeaderboardPosition,
LeaderboardForTopicParams,
LeaderboardForTopicResponse,
LeaderboardParams,
LeaderboardResponse,
TopicFlagsQuery,
TopicFlagsResponse,
} from './api.types'
/**
* Configuring the apisauce instance.
*/
export const DEFAULT_API_CONFIG: ApiConfig = {
url: process.env.EXPO_PUBLIC_API_URL!,
timeout: 10000,
}
/**
* Manages all requests to the API. You can use this class to build out
* various requests that you need to call from your backend API.
*/
export class Api {
apisauce: ApisauceInstance
config: ApiConfig
/**
* Set up our API instance. Keep this lightweight!
*/
constructor(config: ApiConfig = DEFAULT_API_CONFIG) {
this.config = config
this.apisauce = create({
baseURL: this.config.url,
timeout: this.config.timeout,
headers: {
Accept: 'application/json',
},
})
}
async getLeaderboard(params: LeaderboardParams) {
console.log('API getLeaderboard params:', JSON.stringify(params, null, 2))
// Handle search parameter separately to avoid double-encoding
const { search, ...otherParams } = params
if (search) {
// If search is provided, manually construct the URL with the unencoded search term
// This prevents apisauce from encoding the % characters
const paginationJson = JSON.stringify(otherParams.pagination)
const paginationParam = `pagination=${paginationJson}`
const seasonParam = otherParams.season
? `&season=${otherParams.season}`
: ''
const searchParam = `&search=${search}`
console.log('Using custom URL construction for search')
return this.apisauce.get<LeaderboardResponse>(
`/clout/leaderboard-clout?${paginationParam}${seasonParam}${searchParam}`,
)
}
// Otherwise use the standard approach but still format pagination correctly
const requestParams = {
pagination: JSON.stringify(otherParams.pagination),
season: otherParams.season,
}
return this.apisauce.get<LeaderboardResponse>(
'/clout/leaderboard-clout',
requestParams,
)
}
async getTopicsFlags(params: TopicFlagsQuery = {}) {
return this.apisauce.get<TopicFlagsResponse>('/clout/get-topics-flags', {
...params,
})
}
async getLeaderboardMindshareClout() {
return this.apisauce.get<CloutResponse>(
'/clout/leaderboard-mindshare-clout',
)
}
async getLeaderboardMindshareForTopic(topic: string) {
return this.apisauce.get<CloutResponse>(
`/clout/leaderboard-mindshare-for-topic/${topic}`,
)
}
async getLeaderboardForTopic(params: LeaderboardForTopicParams) {
// Handle search parameter separately to avoid double-encoding
const { search, topic, ...otherParams } = params
if (search) {
// If search is provided, manually construct the URL with the unencoded search term
const paginationJson = JSON.stringify(otherParams.pagination)
const paginationParam = `pagination=${paginationJson}`
const searchParam = `&search=${search}`
console.log('Using custom URL construction for topic search')
return this.apisauce.get<LeaderboardForTopicResponse>(
`/clout/leaderboard-for-topic/${topic}?${paginationParam}${searchParam}`,
)
}
// Otherwise use the standard approach but still format pagination correctly
const requestParams = {
pagination: JSON.stringify(otherParams.pagination),
}
return this.apisauce.get<LeaderboardForTopicResponse>(
`/clout/leaderboard-for-topic/${params.topic}`,
requestParams,
)
}
async getTrendingClout() {
return this.apisauce.get<CloutResponse>('/clout/trending')
}
async getMindShareTrending() {
return this.apisauce.get<CloutResponse>(
'/clout/mindshare-trending-deprecated',
)
}
async getHeroFeed(params: HeroFeedParams) {
return this.apisauce.get<HeroFeedResponse>('/hero/feed', {
...params,
})
}
async getCloutHeroQuickOverview(params: CloutHeroQuickOverviewParams) {
return this.apisauce.get<CloutHeroQuickOverviewResponse>(
'/clout/hero-quick-overview',
{
...params,
},
)
}
async getCloudHeroSummary(params: CloudHeroSummaryParams) {
return this.apisauce.get<CloudHeroSummaryRow>('/clout/hero/summary', {
...params,
})
}
async getHeroLeaderboardPositions(heroId: string) {
return this.apisauce.get<HeroLeaderboardPosition[]>(
`/clout/hero/leaderboard-position/${heroId}`,
)
}
}
// Singleton instance of the API for convenience
export const api = new Api()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment