mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
feat(platform): setup and configure orval (#10209)
This pull request sets up and configures Orval for API client generation. It automates the process of creating TypeScript clients from the backend's OpenAPI specification, improving development efficiency and reducing manual code maintenance. ### Changes 🏗️ - Configures Orval with a new configuration file (`orval.config.ts`). - Adds scripts to `package.json` for fetching the OpenAPI spec and generating the API client. - Implements a custom mutator for handling authentication. - Adds API client generation as a step in the CI workflow. - Adds `.gitignore` entry for generated API client files. - Adds a security middleware to prevent caching of sensitive data. ### Checklist 📋 #### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - [x] Verified that the API client is generated correctly. - [x] Confirmed that the custom mutator is functioning as expected for authentication. - [x] Ensured that the new CI workflow step for API client generation is successful. - [x] Tested generated API calls #### For configuration changes: - [x] `.env.example` is updated or already compatible with my changes - [ ] `docker-compose.yml` is updated or already compatible with my changes - [x] I have included a list of my configuration changes in the PR description (under **Changes**)
This commit is contained in:
81
autogpt_platform/frontend/src/api/mutators/custom-mutator.ts
Normal file
81
autogpt_platform/frontend/src/api/mutators/custom-mutator.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { getSupabaseClient } from "@/lib/supabase/getSupabaseClient";
|
||||
|
||||
const BASE_URL =
|
||||
process.env.NEXT_PUBLIC_AGPT_SERVER_BASE_URL || "http://localhost:8006";
|
||||
|
||||
const getBody = <T>(c: Response | Request): Promise<T> => {
|
||||
const contentType = c.headers.get("content-type");
|
||||
|
||||
if (contentType && contentType.includes("application/json")) {
|
||||
return c.json();
|
||||
}
|
||||
|
||||
if (contentType && contentType.includes("application/pdf")) {
|
||||
return c.blob() as Promise<T>;
|
||||
}
|
||||
|
||||
return c.text() as Promise<T>;
|
||||
};
|
||||
|
||||
const getSupabaseToken = async () => {
|
||||
const supabase = await getSupabaseClient();
|
||||
|
||||
const {
|
||||
data: { session },
|
||||
} = (await supabase?.auth.getSession()) || {
|
||||
data: { session: null },
|
||||
};
|
||||
|
||||
return session?.access_token;
|
||||
};
|
||||
|
||||
export const customMutator = async <T = any>(
|
||||
url: string,
|
||||
options: RequestInit & {
|
||||
params?: any;
|
||||
} = {},
|
||||
): Promise<T> => {
|
||||
const { params, ...requestOptions } = options;
|
||||
const method = (requestOptions.method || "GET") as
|
||||
| "GET"
|
||||
| "POST"
|
||||
| "PUT"
|
||||
| "DELETE"
|
||||
| "PATCH";
|
||||
const data = requestOptions.body;
|
||||
const headers: Record<string, string> = {
|
||||
...((requestOptions.headers as Record<string, string>) || {}),
|
||||
};
|
||||
|
||||
const token = await getSupabaseToken();
|
||||
|
||||
if (token) {
|
||||
headers["Authorization"] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
const isFormData = data instanceof FormData;
|
||||
|
||||
// Currently, only two content types are handled here: application/json and multipart/form-data
|
||||
if (!isFormData && data && !headers["Content-Type"]) {
|
||||
headers["Content-Type"] = "application/json";
|
||||
}
|
||||
|
||||
const queryString = params
|
||||
? "?" + new URLSearchParams(params).toString()
|
||||
: "";
|
||||
|
||||
const response = await fetch(`${BASE_URL}${url}${queryString}`, {
|
||||
...requestOptions,
|
||||
method,
|
||||
headers,
|
||||
body: data,
|
||||
});
|
||||
|
||||
const response_data = await getBody<T>(response);
|
||||
|
||||
return {
|
||||
status: response.status,
|
||||
response_data,
|
||||
headers: response.headers,
|
||||
} as T;
|
||||
};
|
||||
6093
autogpt_platform/frontend/src/api/openapi.json
Normal file
6093
autogpt_platform/frontend/src/api/openapi.json
Normal file
File diff suppressed because it is too large
Load Diff
57
autogpt_platform/frontend/src/api/transformers/fix-tags.mjs
Normal file
57
autogpt_platform/frontend/src/api/transformers/fix-tags.mjs
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Transformer function for orval that fixes tags in OpenAPI spec.
|
||||
* 1. Create a set of tags so we have unique values
|
||||
* 2. Then remove public, private, v1, and v2 tags from tags array
|
||||
* 3. Then arrange remaining tags alphabetically and only keep the first one
|
||||
*
|
||||
* @param {OpenAPIObject} inputSchema
|
||||
* @return {OpenAPIObject}
|
||||
*/
|
||||
|
||||
export const tagTransformer = (inputSchema) => {
|
||||
const processedPaths = Object.entries(inputSchema.paths || {}).reduce(
|
||||
(acc, [path, pathItem]) => ({
|
||||
...acc,
|
||||
[path]: Object.entries(pathItem || {}).reduce(
|
||||
(pathItemAcc, [verb, operation]) => {
|
||||
if (typeof operation === "object" && operation !== null) {
|
||||
// 1. Create a set of tags so we have unique values
|
||||
const uniqueTags = Array.from(new Set(operation.tags || []));
|
||||
|
||||
// 2. Remove public, private, v1, and v2 tags from tags array
|
||||
const filteredTags = uniqueTags.filter(
|
||||
(tag) =>
|
||||
!["public", "private"].includes(tag.toLowerCase()) &&
|
||||
!/^v[12]$/i.test(tag),
|
||||
);
|
||||
|
||||
// 3. Arrange tags alphabetically and only keep the first one
|
||||
const sortedTags = filteredTags.sort((a, b) => a.localeCompare(b));
|
||||
const firstTag = sortedTags.length > 0 ? [sortedTags[0]] : [];
|
||||
|
||||
return {
|
||||
...pathItemAcc,
|
||||
[verb]: {
|
||||
...operation,
|
||||
tags: firstTag,
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
...pathItemAcc,
|
||||
[verb]: operation,
|
||||
};
|
||||
},
|
||||
{},
|
||||
),
|
||||
}),
|
||||
{},
|
||||
);
|
||||
|
||||
return {
|
||||
...inputSchema,
|
||||
paths: processedPaths,
|
||||
};
|
||||
};
|
||||
|
||||
export default tagTransformer;
|
||||
Reference in New Issue
Block a user