Skip to content

Commit

Permalink
create api
Browse files Browse the repository at this point in the history
  • Loading branch information
SKairinos committed Aug 14, 2024
1 parent 2ec74a9 commit 5f62c1b
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 138 deletions.
131 changes: 0 additions & 131 deletions src/api/baseQuery.ts

This file was deleted.

93 changes: 93 additions & 0 deletions src/api/createApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { createApi as _createApi, fetchBaseQuery } from "@reduxjs/toolkit/query"

import { SERVICE_API_URL } from "../env"
import { getCsrfCookie, logout } from "../utils/auth"
import defaultTagTypes from "./tagTypes"

// TODO: decide if we want to keep any of this.
// export function handleResponseError(error: FetchBaseQueryError): void {
// if (
// error.status === 400 &&
// typeof error.data === "object" &&
// error.data !== null
// ) {
// // Parse the error's data from snake_case to camelCase.
// snakeCaseToCamelCase(error.data)
// } else if (error.status === 401) {
// // TODO: redirect to appropriate login page based on user type.
// window.location.href = `${PORTAL_BASE_URL}/login/teacher`
// } else {
// // Catch-all error pages by status-code.
// window.location.href = `${PORTAL_BASE_URL}/error/${
// [403, 404].includes(error.status as number) ? error.status : 500
// }`
// }
// }

export default function createApi<TagTypes extends string = never>({
tagTypes = [],
}: {
tagTypes?: readonly TagTypes[]
} = {}) {
const fetch = fetchBaseQuery({
baseUrl: `${SERVICE_API_URL}/`,
credentials: "include",
prepareHeaders: (headers, { type }) => {
if (type === "mutation") {
let csrfToken = getCsrfCookie()
if (csrfToken) headers.set("x-csrftoken", csrfToken)
}

return headers
},
})

const api = _createApi({
// https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#implementing-a-custom-basequery
baseQuery: async (args, api, extraOptions) => {
if (api.type === "mutation" && getCsrfCookie() === undefined) {
// Get the CSRF token.
const { error } = await fetch(
{ url: "/csrf/cookie", method: "GET" },
api,
{},
)

// Validate we got the CSRF token.
if (error !== undefined) {
console.error(error)
// TODO
// window.location.href = `${PORTAL_BASE_URL}/error/500`
}
if (getCsrfCookie() === undefined) {
// TODO
// window.location.href = `${PORTAL_BASE_URL}/error/500`
}
}

// Send the HTTP request and fetch the response.
return await fetch(args, api, extraOptions)
},
tagTypes: [...defaultTagTypes, ...tagTypes],
endpoints: build => ({
logout: build.mutation<null, null>({
query: () => ({
url: "session/logout/",
method: "POST",
}),
async onQueryStarted(_, { dispatch, queryFulfilled }) {
try {
await queryFulfilled
} catch (error) {
console.error("Failed to call logout endpoint...", error)
} finally {
logout()
dispatch(api.util.resetApiState())
}
},
}),
}),
})

return api
}
4 changes: 2 additions & 2 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import baseQuery from "./baseQuery"
import createApi from "./createApi"
import type {
AdminSchoolTeacher,
AdminSchoolTeacherUser,
Expand All @@ -23,7 +23,7 @@ import tagTypes from "./tagTypes"
import urls from "./urls"

export {
baseQuery,
createApi,
tagTypes,
urls,
type AdminSchoolTeacher,
Expand Down
35 changes: 30 additions & 5 deletions src/env.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
export const SERVICE_NAME = import.meta.env.VITE_SERVICE_NAME ?? "REPLACE_ME"
export const API_BASE_URL =
import.meta.env.VITE_API_BASE_URL ?? "http://localhost:8000/api/"
export const PORTAL_BASE_URL =
import.meta.env.VITE_PORTAL_BASE_URL ?? "http://localhost:3000"
/**
* This file contains all of our custom settings we define for our own purposes.
*
* This file is based on:
* https://github.com/ocadotechnology/codeforlife-package-python/blob/main/codeforlife/settings/custom.py
*/

// Shorthand to access environment variables.
const env = import.meta.env
export default env

// The name of the current service.
export const SERVICE_NAME = env.VITE_SERVICE_NAME ?? "REPLACE_ME"

// If the current service the root service. This will only be true for portal.
export const SERVICE_IS_ROOT = Boolean(Number(env.SERVICE_IS_ROOT ?? "0"))

// The protocol, domain and port of the current service.
export const SERVICE_PROTOCOL = env.SERVICE_PROTOCOL ?? "http"
export const SERVICE_DOMAIN = env.SERVICE_DOMAIN ?? "localhost"
export const SERVICE_PORT = Number(env.SERVICE_PORT ?? "8000")

// The base url of the current service.
// The root service does not need its name included in the base url.
export const SERVICE_BASE_URL =
`${SERVICE_PROTOCOL}://${SERVICE_DOMAIN}:${SERVICE_PORT}` +
(SERVICE_IS_ROOT ? "" : `/${SERVICE_NAME}`)

// The api url of the current service.
export const SERVICE_API_URL = `${SERVICE_BASE_URL}/api`

0 comments on commit 5f62c1b

Please sign in to comment.