diff --git a/src/api.js b/src/api.ts similarity index 79% rename from src/api.js rename to src/api.ts index 3fd8e01c6..9a4852ca7 100644 --- a/src/api.js +++ b/src/api.ts @@ -12,21 +12,29 @@ import { import {CSPNonce, CSRFToken, ContentLanguage, IsFormDesigner} from './headers'; import {setLanguage} from './i18n'; -const fetchDefaults = { - credentials: 'include', // required for Firefox 60, which is used in werkplekken +interface ApiCallOptions extends Omit { + headers?: Record; +} + +const fetchDefaults: ApiCallOptions = { + credentials: 'include', }; const SessionExpiresInHeader = 'X-Session-Expires-In'; -let sessionExpiresAt = createState({expiry: null}); +interface SessionExpiryState { + expiry: Date | null; +} + +const sessionExpiresAt = createState({expiry: null}); -export const updateSessionExpiry = seconds => { +export const updateSessionExpiry = (seconds: number) => { const newExpiry = new Date(); newExpiry.setSeconds(newExpiry.getSeconds() + seconds); sessionExpiresAt.setValue({expiry: newExpiry}); }; -const throwForStatus = async response => { +const throwForStatus = async (response: Response) => { if (response.ok) return; let responseData = null; @@ -75,7 +83,7 @@ const throwForStatus = async response => { throw new ErrorClass(errorMessage, response.status, responseData.detail, responseData.code); }; -const addHeaders = (headers, method) => { +const addHeaders = (headers: Record | undefined, method: string) => { if (!headers) headers = {}; // add the CSP nonce request header in case the backend needs to do any post-processing @@ -94,10 +102,10 @@ const addHeaders = (headers, method) => { return headers; }; -const updateStoredHeadersValues = headers => { +const updateStoredHeadersValues = (headers: Headers) => { const sessionExpiry = headers.get(SessionExpiresInHeader); if (sessionExpiry) { - updateSessionExpiry(parseInt(sessionExpiry), 10); + updateSessionExpiry(parseInt(sessionExpiry, 10)); } const CSRFTokenValue = headers.get(CSRFToken.headerName); @@ -117,7 +125,7 @@ const updateStoredHeadersValues = headers => { } }; -const apiCall = async (url, opts = {}) => { +const apiCall = async (url: string, opts: ApiCallOptions = {}) => { const method = opts.method || 'GET'; const options = {...fetchDefaults, ...opts}; options.headers = addHeaders(options.headers, method); @@ -129,7 +137,11 @@ const apiCall = async (url, opts = {}) => { return response; }; -const get = async (url, params = {}, multiParams = []) => { +const get = async ( + url: string, + params: Record = {}, + multiParams: Record[] = [] +) => { let searchParams = new URLSearchParams(); if (Object.keys(params).length) { searchParams = new URLSearchParams(params); @@ -146,12 +158,12 @@ const get = async (url, params = {}, multiParams = []) => { return data; }; -const _unsafe = async (method = 'POST', url, data, signal) => { - const opts = { +const _unsafe = async (method = 'POST', url: string, data: any, signal?: AbortSignal) => { + const opts: ApiCallOptions = { method, headers: { 'Content-Type': 'application/json', - [CSRFToken.headerName]: CSRFToken.getValue(), + [CSRFToken.headerName]: CSRFToken.getValue() ?? '', }, }; if (data) { @@ -169,22 +181,22 @@ const _unsafe = async (method = 'POST', url, data, signal) => { }; }; -const post = async (url, data, signal) => { +const post = async (url: string, data: any, signal?: AbortSignal) => { const resp = await _unsafe('POST', url, data, signal); return resp; }; -const patch = async (url, data = {}) => { +const patch = async (url: string, data: any = {}) => { const resp = await _unsafe('PATCH', url, data); return resp; }; -const put = async (url, data = {}) => { +const put = async (url: string, data: any = {}) => { const resp = await _unsafe('PUT', url, data); return resp; }; -const destroy = async url => { +const destroy = async (url: string) => { const opts = { method: 'DELETE', }; diff --git a/src/components/AppDebug.jsx b/src/components/AppDebug.tsx similarity index 65% rename from src/components/AppDebug.jsx rename to src/components/AppDebug.tsx index 3df89e751..7e5ba2791 100644 --- a/src/components/AppDebug.jsx +++ b/src/components/AppDebug.tsx @@ -1,20 +1,25 @@ import {FormattedDate, FormattedRelativeTime, useIntl} from 'react-intl'; import {useState as useGlobalState} from 'state-pool'; -import {sessionExpiresAt} from 'api'; -import {getVersion} from 'utils'; +import {sessionExpiresAt} from '@/api'; +import {getVersion} from '@/utils'; -const DebugInfo = ({label, value, children}) => ( +export interface DebugInfoProps { + label: string; + value?: string; + children?: React.ReactNode; +} + +const DebugInfo: React.FC = ({label, value, children}) => (
{label}
{value ?? children}
); -const AppDebug = () => { +const AppDebug: React.FC = () => { const {locale} = useIntl(); const [{expiry}] = useGlobalState(sessionExpiresAt); - const expiryDelta = (expiry - new Date()) / 1000; return (
@@ -23,7 +28,11 @@ const AppDebug = () => { <>  ( - + ) ) : (