import _axios, { AxiosInstance } from 'axios' export type IType = 'character' | 'vocabulary' | 'sentence' export interface IEntry { id: string entry: string[] reading: string[] translation: string[] type: IType description: string tag: string[] } export type ILookup = T & { offset?: number limit?: number } export interface ILookupResult { result: T[] count: number } class Api { axios: AxiosInstance _isAuthorized = true _user = '' constructor() { this.axios = _axios.create() } async setWanikaniApiKey(apiKey?: string) { const setApiKey = () => { if (apiKey) { this.axios.defaults.headers.common.Authorization = `Bearer ${apiKey}` } else { delete this.axios.defaults.headers.common.Authorization } } setApiKey() const r = await this.user_getSettings() if (r) return r apiKey = '' setApiKey() return null } async isAuthorized(): Promise { if (this._isAuthorized && !this._user) { const r = await this.user_getSettings() if (r) { this._user = r.identifier this._isAuthorized = true } } return this._isAuthorized } async user_getSettings() { const r = await this.axios .get('/api/user', { params: { select: 'level,levelMin,identifier', }, }) .then( (r) => r.data as { level: number levelMin?: number identifier: string } ) .then((r) => ({ ...r, levelMin: r.levelMin || 1, })) .catch(() => null) if (!r) { return } return r } async user_updateSettings(u: { levelMin: number }) { return await this.axios.patch('/api/user', u) } async quiz_getMany(params: { entries: string[] select: string[] type?: string direction?: string }) { return await this.axios.post('/api/quiz/getMany', params).then( (r) => r.data as { result: { id: string entry: string }[] } ) } async quiz_create(payload: { entries: string[]; type: IType }) { return await this.axios.put('/api/quiz', payload).then( (r) => r.data as { result: { ids: string[] }[] } ) } async quiz_deleteMany(params: { entries: string[]; type: IType }) { return await this.axios.post('/api/quiz/deleteMany', params) } async extra_getQuery(params: ILookup<{ q: string }>) { params.offset = params.offset || 0 params.limit = params.limit || 5 return await this.axios .get('/api/extra/q', { params }) .then((r) => r.data as ILookupResult) } async extra_create(payload: Omit) { return await this.axios .put('/api/extra', payload) .then((r) => r.data as { id: string }) } async extra_update(payload: IEntry) { return await this.axios.patch('/api/extra', payload, { params: { id: payload.id }, }) } async extra_delete(params: { id: string }) { return await this.axios.delete('/api/extra', { params, }) } async character_getRadical(params: { entry: string }) { return await this.axios.get('/api/character/radical', { params }).then( (r) => r.data as { result: { sub: string[] sup: string[] variant: string[] visual: string[] } | null } ) } async character_getVocabulary( params: ILookup<{ entry: string; distinct?: 'id' }> ) { return await this.axios.get('/api/character/vocabulary', { params }).then( (r) => r.data as ILookupResult<{ entry: string }> ) } async character_getSentence( params: ILookup<{ entry: string; distinct?: 'id' }> ) { return await this.axios.get('/api/character/sentence', { params }).then( (r) => r.data as ILookupResult<{ entry: string }> ) } async all_getRandom(params: { type: IType }) { return await this.axios.get('/api/all/random', { params }).then( (r) => r.data as { result: string level: number } ) } async all_getQuery(params: ILookup<{ q: string }>) { params.offset = params.offset || 0 params.limit = params.limit || 5 return await this.axios.get('/api/all/q', { params }).then( (r) => r.data as ILookupResult<{ entry: string type: IType }> ) } async all_getLookup(params: ILookup<{ entry: string; type: IType }>) { params.offset = params.offset || 0 params.limit = params.limit || 5 return await this.axios .get('/api/all', { params, }) .then( (r) => r.data as ILookupResult< IEntry & { level?: number } > ) } async all_getReading(params: { entry: string }) { return await this.axios .get('/api/all/reading', { params, }) .then( (r) => r.data as { result: string } ) } async all_getMeaning(params: { entry: string }) { return await this.axios .get('/api/all/meaning', { params, }) .then( (r) => r.data as { result: { entry?: string meaning: string }[] } ) } } export const api = new Api()