Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 62x 5721x 5721x 5721x 5721x 5721x 5721x 5721x 5451x 5721x 5721x 5721x 5721x 5721x 62x 62x | // Template API used by the generated RTK Query client. The generated code imports
// `emptySplitApi`, while this module centralises the shared base URL and the
// flowsheet query/body injection used throughout the app.
// see also (openapi-config.json)
// and https://redux-toolkit.js.org/rtk-query/usage/code-generation#usage
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { toast } from "sonner";
import {
getCachedFlowsheetAccess,
isReadOnlyMutationBlocked,
} from "@/lib/flowsheetAccess";
import { baseUrl, resolveApiUrl } from "./apiBaseUrl";
const defaultBaseQuery = fetchBaseQuery({
baseUrl,
credentials: "include",
});
const customBaseQuery = async (args, api, extraOptions) => {
const url = document.URL;
const match = url.match(/\/project\/(\d+)/);
const flowsheetId = match ? Number(match[1]) : null;
const reducerPath = emptySplitApi.reducerPath;
const originalUrl = typeof args === "string" ? args : args.url;
const argsUrl = new URL(resolveApiUrl(originalUrl));
// RTK Query passes either a bare URL string for simple GETs or a request
// object with explicit method/body fields for richer requests.
const method =
typeof args === "string" ? "GET" : (args.method?.toUpperCase() ?? "GET");
if (flowsheetId) {
argsUrl.searchParams.set("flowsheet", flowsheetId.toString());
}
if (typeof args === "string") {
args = argsUrl.toString();
} else if (typeof args === "object") {
// Inject flowsheet into body (for POST, PUT, etc.)
const isJson =
args.body &&
typeof args.body === "object" &&
!(args.body instanceof FormData);
const newBody =
flowsheetId && isJson
? { ...args.body, flowsheet: flowsheetId }
: args.body;
args = {
...args,
url: argsUrl.toString(),
body: newBody,
};
}
const access = getCachedFlowsheetAccess(
api.getState() as Record<string, unknown>,
reducerPath,
flowsheetId,
);
if (
isReadOnlyMutationBlocked({
method,
pathname: argsUrl.pathname,
access,
})
) {
// Return a synthetic 403 before the request leaves the browser so every
// mutation endpoint gets consistent read-only behaviour, even if the UI
// surface forgot to disable a control.
toast.warning("This flowsheet is read-only", {
description: "Make a copy to edit or solve this flowsheet.",
});
return {
error: {
status: 403,
data: {
error: "This flowsheet is shared with read-only access.",
},
},
};
}
return defaultBaseQuery(args, api, extraOptions);
};
// initialize an empty api service that we'll inject endpoints into later as needed
export const emptySplitApi = createApi({
baseQuery: customBaseQuery,
endpoints: () => ({}),
});
|