150 lines
3.8 KiB
TypeScript
150 lines
3.8 KiB
TypeScript
|
/*
|
||
|
GoToSocial
|
||
|
Copyright (C) GoToSocial Authors admin@gotosocial.org
|
||
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU Affero General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU Affero General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU Affero General Public License
|
||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
|
||
|
import type {
|
||
|
BaseQueryFn,
|
||
|
FetchArgs,
|
||
|
FetchBaseQueryError,
|
||
|
} from '@reduxjs/toolkit/query/react';
|
||
|
import { serialize as serializeForm } from "object-to-formdata";
|
||
|
|
||
|
import type { RootState } from '../../redux/store';
|
||
|
|
||
|
/**
|
||
|
* GTSFetchArgs extends standard FetchArgs used by
|
||
|
* RTK Query with a couple helpers of our own.
|
||
|
*/
|
||
|
export interface GTSFetchArgs extends FetchArgs {
|
||
|
/**
|
||
|
* If provided, will be used as base URL. Else,
|
||
|
* will fall back to authorized instance as baseUrl.
|
||
|
*/
|
||
|
baseUrl?: string;
|
||
|
/**
|
||
|
* If true, and no args.body is set, or args.body is empty,
|
||
|
* then a null response will be returned from the API call.
|
||
|
*/
|
||
|
discardEmpty?: boolean;
|
||
|
/**
|
||
|
* If true, then args.body will be serialized
|
||
|
* as FormData before submission.
|
||
|
*/
|
||
|
asForm?: boolean;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* gtsBaseQuery wraps the redux toolkit fetchBaseQuery with some helper functionality.
|
||
|
*
|
||
|
* For an explainer of what's happening in this function, see:
|
||
|
* - https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#customizing-queries-with-basequery
|
||
|
* - https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#constructing-a-dynamic-base-url-using-redux-state
|
||
|
*
|
||
|
* @param args
|
||
|
* @param api
|
||
|
* @param extraOptions
|
||
|
* @returns
|
||
|
*/
|
||
|
const gtsBaseQuery: BaseQueryFn<
|
||
|
string | GTSFetchArgs,
|
||
|
any,
|
||
|
FetchBaseQueryError
|
||
|
> = async (args, api, extraOptions) => {
|
||
|
// Retrieve state at the moment
|
||
|
// this function was called.
|
||
|
const state = api.getState() as RootState;
|
||
|
const { instanceUrl, token } = state.oauth;
|
||
|
|
||
|
// Derive baseUrl dynamically.
|
||
|
let baseUrl: string;
|
||
|
|
||
|
// Check if simple string baseUrl provided
|
||
|
// as args, or if more complex args provided.
|
||
|
if (typeof args === "string") {
|
||
|
baseUrl = args;
|
||
|
} else {
|
||
|
if (args.baseUrl != undefined) {
|
||
|
baseUrl = args.baseUrl;
|
||
|
} else {
|
||
|
baseUrl = instanceUrl;
|
||
|
}
|
||
|
|
||
|
if (args.discardEmpty) {
|
||
|
if (args.body == undefined || Object.keys(args.body).length == 0) {
|
||
|
return { data: null };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (args.asForm) {
|
||
|
args.body = serializeForm(args.body, {
|
||
|
// Array indices, for profile fields.
|
||
|
indices: true,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Delete any of our extended arguments
|
||
|
// to avoid confusing fetchBaseQuery.
|
||
|
delete args.baseUrl;
|
||
|
delete args.discardEmpty;
|
||
|
delete args.asForm;
|
||
|
}
|
||
|
|
||
|
if (!baseUrl) {
|
||
|
return {
|
||
|
error: {
|
||
|
status: 400,
|
||
|
statusText: 'Bad Request',
|
||
|
data: {"error":"No baseUrl set for request"},
|
||
|
},
|
||
|
};
|
||
|
}
|
||
|
|
||
|
return fetchBaseQuery({
|
||
|
baseUrl: baseUrl,
|
||
|
prepareHeaders: (headers) => {
|
||
|
if (token != undefined) {
|
||
|
headers.set('Authorization', token);
|
||
|
}
|
||
|
headers.set("Accept", "application/json");
|
||
|
return headers;
|
||
|
},
|
||
|
})(args, api, extraOptions);
|
||
|
};
|
||
|
|
||
|
export const gtsApi = createApi({
|
||
|
reducerPath: "api",
|
||
|
baseQuery: gtsBaseQuery,
|
||
|
tagTypes: [
|
||
|
"Auth",
|
||
|
"Emoji",
|
||
|
"Reports",
|
||
|
"Account",
|
||
|
"InstanceRules",
|
||
|
],
|
||
|
endpoints: (builder) => ({
|
||
|
instance: builder.query<any, void>({
|
||
|
query: () => ({
|
||
|
url: `/api/v1/instance`
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
});
|
||
|
|
||
|
export const { useInstanceQuery } = gtsApi;
|