Files
fnx_web/svelte/src/lib/NovaAPI.ts

186 lines
4.3 KiB
TypeScript

// Response types
// ==============
import { user } from "./UserStore"
export type GenericResponse = {
value: string,
message: string,
errors?: GenericResponse[],
extra?: { [index: string]: Object },
}
export type User = {
username: string,
email: string,
otp_enabled: boolean,
subscription: Subscription,
storage_space_used: number,
filesystem_storage_used: number,
filesystem_node_count: number,
is_admin: boolean,
balance_micro_eur: number,
hotlinking_enabled: boolean,
monthly_transfer_cap: number,
monthly_transfer_used: number,
file_viewer_branding: Map<string, string>,
file_embed_domains: string,
skip_file_viewer: boolean,
affiliate_user_name: string,
checkout_country: string,
checkout_name: string,
checkout_provider: string,
}
export type Subscription = {
id: string,
name: string,
type: string,
file_size_limit: number,
storage_limit: number,
price_per_tb_storage: number,
price_per_tb_bandwidth: number,
monthly_transfer_cap: number,
file_sharing: boolean,
}
// Utility funcs
// =============
export const get_endpoint = () => {
if ((window as any).api_endpoint !== undefined) {
return (window as any).api_endpoint as string
}
console.warn("api_endpoint property is not defined on window")
return "/api"
}
export const get_hostname = () => {
if ((window as any).server_hostname !== undefined) {
return (window as any).server_hostname as string
}
console.warn("server_hostname property is not defined on window")
return "undefined"
}
export const check_response = async (resp: Response) => {
let text = await resp.text()
if (resp.status >= 400) {
let error: any
try {
error = JSON.parse(text) as GenericResponse
} catch (err) {
error = text
}
throw error
}
return JSON.parse(text)
}
export const dict_to_form = (dict: Object) => {
let form = new FormData()
for (let key of Object.keys(dict)) {
if (dict[key] === undefined) {
continue
} else if (dict[key] instanceof Date) {
form.append(key, new Date(dict[key]).toISOString())
} else if (typeof dict[key] === "object") {
form.append(key, JSON.stringify(dict[key]))
} else {
form.append(key, dict[key])
}
}
return form
}
// API methods
// ===========
export type UserSession = {
auth_key: string,
creation_ip_address: string,
user_agent: string,
app_name: string,
creation_time: string,
last_used_time: string,
valid_domains: string[],
}
// If cached_user is undefined it means that the value is not initialized yet,
// null means the user is not logged in
let cached_user: User = undefined
// The request which is currently in flight. Callers which arrive while the
// request is still running share this promise, so the user is only requested
// from the server once
let user_request: Promise<User> | null = null
export const get_user = async (): Promise<User> => {
if (cached_user !== undefined) {
return cached_user
}
if (user_request === null) {
user_request = request_user()
}
const u = await user_request
if (u === undefined) {
// The request failed. Clear it so the next caller tries again
user_request = null
}
return u
}
const request_user = async (): Promise<User> => {
try {
let resp = await fetch(get_endpoint() + "/user")
if (resp.status === 401) {
// User is not authenticated
cached_user = null
} else if (resp.status >= 400) {
throw await resp.text()
} else {
cached_user = (await resp.json()) as User
}
} catch (err) {
alert("failed to fetch user:\n" + err)
}
user.set(cached_user)
return cached_user
}
export const put_user = async (data: Object) => {
await check_response(await fetch(
get_endpoint() + "/user",
{ method: "PUT", body: dict_to_form(data) },
))
// Update the user store
for (let key of Object.keys(data)) {
cached_user[key] = data[key]
}
user.set(cached_user)
}
export const logout_user = async (redirect_path: string) => {
await check_response(await fetch(
get_endpoint() + "/user/session",
{ method: "DELETE" },
))
// document.cookie = "pd_auth_key=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
window.location.pathname = redirect_path
}
export type VATRate = {
name: string,
vat: number,
alpha2: string,
alpha3: string,
}
export const get_misc_vat_rate = async (country_code: string) => {
return await check_response(await fetch(get_endpoint() + "/misc/vat_rate/" + country_code)) as VATRate
}