mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
fix: openapi schemas
This commit is contained in:
@@ -74,6 +74,8 @@ function checkRouteExists(pathname: string) {
|
|||||||
/^\/api\/health\/?$/,
|
/^\/api\/health\/?$/,
|
||||||
/^\/api\/google\/drive\/callback\/?$/,
|
/^\/api\/google\/drive\/callback\/?$/,
|
||||||
// v1 external API
|
// v1 external API
|
||||||
|
/^\/api\/v1\/docs\/?$/,
|
||||||
|
/^\/api\/v1\/openapi\/?$/,
|
||||||
/^\/api\/v1\/agents\/?$/,
|
/^\/api\/v1\/agents\/?$/,
|
||||||
/^\/api\/v1\/agents\/[^/]+\/?$/,
|
/^\/api\/v1\/agents\/[^/]+\/?$/,
|
||||||
/^\/api\/v1\/agents\/[^/]+\/key\/?$/,
|
/^\/api\/v1\/agents\/[^/]+\/key\/?$/,
|
||||||
|
|||||||
@@ -1,23 +1,8 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { OpenAPIRegistry } from "@asteasolutions/zod-to-openapi";
|
import { OpenAPIRegistry } from "@asteasolutions/zod-to-openapi";
|
||||||
import "@/lib/api-v1/openapi/registry";
|
import "@/lib/api-v1/openapi/registry";
|
||||||
|
import {AgentSchema} from "@/features/agents/agents.schema";
|
||||||
const AgentSchema = z
|
import {agentSchema} from "@/db/schema/08_agent";
|
||||||
.object({
|
|
||||||
id: z.string().uuid(),
|
|
||||||
slug: z.string(),
|
|
||||||
version: z.string().nullable(),
|
|
||||||
name: z.string(),
|
|
||||||
healthErrorCount: z.number().int().nullable(),
|
|
||||||
description: z.string(),
|
|
||||||
isArchived: z.boolean().nullable(),
|
|
||||||
lastContact: z.string().datetime().nullable(),
|
|
||||||
organizationId: z.string().uuid().nullable(),
|
|
||||||
createdAt: z.string().datetime(),
|
|
||||||
updatedAt: z.string().datetime().nullable(),
|
|
||||||
deletedAt: z.string().datetime().nullable(),
|
|
||||||
})
|
|
||||||
.openapi("Agent");
|
|
||||||
|
|
||||||
const UuidParam = z
|
const UuidParam = z
|
||||||
.string()
|
.string()
|
||||||
@@ -25,15 +10,17 @@ const UuidParam = z
|
|||||||
.openapi({ example: "123e4567-e89b-12d3-a456-426614174000" });
|
.openapi({ example: "123e4567-e89b-12d3-a456-426614174000" });
|
||||||
|
|
||||||
const security = [{ apiKeyAuth: [] }];
|
const security = [{ apiKeyAuth: [] }];
|
||||||
|
const tags = ["Agents"];
|
||||||
|
|
||||||
const ErrorSchema = z.object({ error: z.string() });
|
const ErrorSchema = z.object({ error: z.string() });
|
||||||
|
|
||||||
export function registerAgentRoutes(registry: OpenAPIRegistry) {
|
export function registerAgentRoutes(registry: OpenAPIRegistry) {
|
||||||
registry.register("Agent", AgentSchema);
|
registry.register("Agent", z.object(agentSchema.shape).openapi("Agent"));
|
||||||
|
|
||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/agents",
|
path: "/agents",
|
||||||
|
tags,
|
||||||
summary:"List agents",
|
summary:"List agents",
|
||||||
security,
|
security,
|
||||||
responses: {
|
responses: {
|
||||||
@@ -41,7 +28,7 @@ export function registerAgentRoutes(registry: OpenAPIRegistry) {
|
|||||||
description: "List of accessible agents",
|
description: "List of accessible agents",
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
schema: z.object({ data: z.array(AgentSchema) }),
|
schema: z.object({ data: z.array(agentSchema) }),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -59,6 +46,7 @@ export function registerAgentRoutes(registry: OpenAPIRegistry) {
|
|||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/agents",
|
path: "/agents",
|
||||||
|
tags,
|
||||||
summary:"Create an agent",
|
summary:"Create an agent",
|
||||||
security,
|
security,
|
||||||
request: {
|
request: {
|
||||||
@@ -107,6 +95,7 @@ export function registerAgentRoutes(registry: OpenAPIRegistry) {
|
|||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/agents/{id}",
|
path: "/agents/{id}",
|
||||||
|
tags,
|
||||||
summary:"Get agent by ID",
|
summary:"Get agent by ID",
|
||||||
security,
|
security,
|
||||||
request: { params: z.object({ id: UuidParam }) },
|
request: { params: z.object({ id: UuidParam }) },
|
||||||
@@ -139,6 +128,7 @@ export function registerAgentRoutes(registry: OpenAPIRegistry) {
|
|||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "delete",
|
method: "delete",
|
||||||
path: "/agents/{id}",
|
path: "/agents/{id}",
|
||||||
|
tags,
|
||||||
summary:"Delete agent",
|
summary:"Delete agent",
|
||||||
security,
|
security,
|
||||||
request: { params: z.object({ id: UuidParam }) },
|
request: { params: z.object({ id: UuidParam }) },
|
||||||
@@ -166,6 +156,7 @@ export function registerAgentRoutes(registry: OpenAPIRegistry) {
|
|||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/agents/{id}/key",
|
path: "/agents/{id}/key",
|
||||||
|
tags,
|
||||||
summary:"Get agent edge key",
|
summary:"Get agent edge key",
|
||||||
security,
|
security,
|
||||||
request: { params: z.object({ id: UuidParam }) },
|
request: { params: z.object({ id: UuidParam }) },
|
||||||
|
|||||||
@@ -1,70 +1,36 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { OpenAPIRegistry } from "@asteasolutions/zod-to-openapi";
|
import { OpenAPIRegistry } from "@asteasolutions/zod-to-openapi";
|
||||||
import "@/lib/api-v1/openapi/registry";
|
import "@/lib/api-v1/openapi/registry";
|
||||||
|
import { databaseSchema, backupSchema, restorationSchema } from "@/db/schema/07_database";
|
||||||
|
import { backupStorageSchema } from "@/db/schema/14_storage-backup";
|
||||||
|
|
||||||
const DbmsEnum = z.enum([
|
const datetimeNullable = z.string().datetime().nullable();
|
||||||
"postgresql",
|
const datetime = z.string().datetime();
|
||||||
"mysql",
|
const commonTimestamps = {
|
||||||
"mariadb",
|
createdAt: datetime,
|
||||||
"mongodb",
|
updatedAt: datetimeNullable,
|
||||||
"sqlite",
|
deletedAt: datetimeNullable,
|
||||||
"redis",
|
};
|
||||||
"valkey",
|
|
||||||
"firebird",
|
|
||||||
"mssql",
|
|
||||||
]);
|
|
||||||
|
|
||||||
const StatusEnum = z.enum(["waiting", "ongoing", "failed", "success"]);
|
|
||||||
|
|
||||||
const BackupStorageStatusEnum = z.enum(["pending", "success", "failed"]);
|
|
||||||
|
|
||||||
const DatabaseSchema = z
|
const DatabaseSchema = z
|
||||||
.object({
|
.object({
|
||||||
id: z.string().uuid(),
|
...databaseSchema.shape,
|
||||||
agentDatabaseId: z.string().uuid(),
|
lastContact: datetimeNullable,
|
||||||
name: z.string(),
|
...commonTimestamps,
|
||||||
dbms: DbmsEnum,
|
|
||||||
description: z.string().nullable(),
|
|
||||||
backupPolicy: z.string().nullable(),
|
|
||||||
isWaitingForBackup: z.boolean(),
|
|
||||||
backupToRestore: z.string().nullable(),
|
|
||||||
healthErrorCount: z.number().int().nullable(),
|
|
||||||
agentId: z.string().uuid(),
|
|
||||||
lastContact: z.string().datetime().nullable(),
|
|
||||||
projectId: z.string().uuid().nullable(),
|
|
||||||
createdAt: z.string().datetime(),
|
|
||||||
updatedAt: z.string().datetime().nullable(),
|
|
||||||
deletedAt: z.string().datetime().nullable(),
|
|
||||||
})
|
})
|
||||||
.openapi("Database");
|
.openapi("Database");
|
||||||
|
|
||||||
const BackupStorageSchema = z
|
const BackupStorageSchema = z
|
||||||
.object({
|
.object({
|
||||||
id: z.string().uuid(),
|
...backupStorageSchema.shape,
|
||||||
backupId: z.string().uuid(),
|
...commonTimestamps,
|
||||||
storageChannelId: z.string().uuid(),
|
|
||||||
status: BackupStorageStatusEnum,
|
|
||||||
path: z.string().nullable(),
|
|
||||||
size: z.number().nullable(),
|
|
||||||
checksum: z.string().nullable(),
|
|
||||||
createdAt: z.string().datetime(),
|
|
||||||
updatedAt: z.string().datetime().nullable(),
|
|
||||||
deletedAt: z.string().datetime().nullable(),
|
|
||||||
})
|
})
|
||||||
.openapi("BackupStorage");
|
.openapi("BackupStorage");
|
||||||
|
|
||||||
const BackupSchema = z
|
const BackupSchema = z
|
||||||
.object({
|
.object({
|
||||||
id: z.string().uuid(),
|
...backupSchema.shape,
|
||||||
status: StatusEnum,
|
...commonTimestamps,
|
||||||
file: z.string().nullable(),
|
|
||||||
fileSize: z.number().nullable(),
|
|
||||||
databaseId: z.string().uuid(),
|
|
||||||
imported: z.boolean().nullable(),
|
|
||||||
migrated: z.boolean().nullable(),
|
|
||||||
createdAt: z.string().datetime(),
|
|
||||||
updatedAt: z.string().datetime().nullable(),
|
|
||||||
deletedAt: z.string().datetime().nullable(),
|
|
||||||
})
|
})
|
||||||
.openapi("Backup");
|
.openapi("Backup");
|
||||||
|
|
||||||
@@ -74,14 +40,8 @@ const BackupWithStoragesSchema = BackupSchema.extend({
|
|||||||
|
|
||||||
const RestorationSchema = z
|
const RestorationSchema = z
|
||||||
.object({
|
.object({
|
||||||
id: z.string().uuid(),
|
...restorationSchema.shape,
|
||||||
status: StatusEnum,
|
...commonTimestamps,
|
||||||
backupStorageId: z.string().uuid().nullable(),
|
|
||||||
backupId: z.string().uuid(),
|
|
||||||
databaseId: z.string().uuid().nullable(),
|
|
||||||
createdAt: z.string().datetime(),
|
|
||||||
updatedAt: z.string().datetime().nullable(),
|
|
||||||
deletedAt: z.string().datetime().nullable(),
|
|
||||||
})
|
})
|
||||||
.openapi("Restoration");
|
.openapi("Restoration");
|
||||||
|
|
||||||
@@ -91,6 +51,7 @@ const UuidParam = z
|
|||||||
.openapi({ example: "123e4567-e89b-12d3-a456-426614174000" });
|
.openapi({ example: "123e4567-e89b-12d3-a456-426614174000" });
|
||||||
|
|
||||||
const security = [{ apiKeyAuth: [] }];
|
const security = [{ apiKeyAuth: [] }];
|
||||||
|
const tags = ["Databases"];
|
||||||
|
|
||||||
const ErrorSchema = z.object({ error: z.string() });
|
const ErrorSchema = z.object({ error: z.string() });
|
||||||
|
|
||||||
@@ -104,6 +65,7 @@ export function registerDatabaseRoutes(registry: OpenAPIRegistry) {
|
|||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/databases",
|
path: "/databases",
|
||||||
|
tags,
|
||||||
summary:"List databases",
|
summary:"List databases",
|
||||||
security,
|
security,
|
||||||
responses: {
|
responses: {
|
||||||
@@ -129,6 +91,7 @@ export function registerDatabaseRoutes(registry: OpenAPIRegistry) {
|
|||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/databases/{id}",
|
path: "/databases/{id}",
|
||||||
|
tags,
|
||||||
summary:"Get database by ID",
|
summary:"Get database by ID",
|
||||||
security,
|
security,
|
||||||
request: { params: z.object({ id: UuidParam }) },
|
request: { params: z.object({ id: UuidParam }) },
|
||||||
@@ -163,6 +126,7 @@ export function registerDatabaseRoutes(registry: OpenAPIRegistry) {
|
|||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/databases/{id}/status",
|
path: "/databases/{id}/status",
|
||||||
|
tags,
|
||||||
summary:"Get database status",
|
summary:"Get database status",
|
||||||
security,
|
security,
|
||||||
request: { params: z.object({ id: UuidParam }) },
|
request: { params: z.object({ id: UuidParam }) },
|
||||||
@@ -174,7 +138,7 @@ export function registerDatabaseRoutes(registry: OpenAPIRegistry) {
|
|||||||
schema: z.object({
|
schema: z.object({
|
||||||
data: z.object({
|
data: z.object({
|
||||||
isWaitingForBackup: z.boolean().nullable(),
|
isWaitingForBackup: z.boolean().nullable(),
|
||||||
lastContact: z.string().datetime().nullable(),
|
lastContact: datetimeNullable,
|
||||||
latestBackup: BackupSchema.nullable(),
|
latestBackup: BackupSchema.nullable(),
|
||||||
latestRestoration: RestorationSchema.nullable(),
|
latestRestoration: RestorationSchema.nullable(),
|
||||||
}),
|
}),
|
||||||
@@ -204,6 +168,7 @@ export function registerDatabaseRoutes(registry: OpenAPIRegistry) {
|
|||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/databases/{id}/backup",
|
path: "/databases/{id}/backup",
|
||||||
|
tags,
|
||||||
summary:"List backups for a database",
|
summary:"List backups for a database",
|
||||||
security,
|
security,
|
||||||
request: { params: z.object({ id: UuidParam }) },
|
request: { params: z.object({ id: UuidParam }) },
|
||||||
@@ -238,6 +203,7 @@ export function registerDatabaseRoutes(registry: OpenAPIRegistry) {
|
|||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/databases/{id}/backup",
|
path: "/databases/{id}/backup",
|
||||||
|
tags,
|
||||||
summary:"Trigger a backup for a database",
|
summary:"Trigger a backup for a database",
|
||||||
security,
|
security,
|
||||||
request: { params: z.object({ id: UuidParam }) },
|
request: { params: z.object({ id: UuidParam }) },
|
||||||
@@ -274,6 +240,7 @@ export function registerDatabaseRoutes(registry: OpenAPIRegistry) {
|
|||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/databases/{id}/backup/{backupId}",
|
path: "/databases/{id}/backup/{backupId}",
|
||||||
|
tags,
|
||||||
summary:"Get a specific backup with storage details",
|
summary:"Get a specific backup with storage details",
|
||||||
security,
|
security,
|
||||||
request: {
|
request: {
|
||||||
@@ -310,6 +277,7 @@ export function registerDatabaseRoutes(registry: OpenAPIRegistry) {
|
|||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/databases/{id}/restore",
|
path: "/databases/{id}/restore",
|
||||||
|
tags,
|
||||||
summary:"Restore a database from a backup",
|
summary:"Restore a database from a backup",
|
||||||
security,
|
security,
|
||||||
request: {
|
request: {
|
||||||
|
|||||||
@@ -21,5 +21,9 @@ export function buildSpec() {
|
|||||||
},
|
},
|
||||||
servers: [{ url: "/api/v1" }],
|
servers: [{ url: "/api/v1" }],
|
||||||
security: [{ apiKeyAuth: [] }],
|
security: [{ apiKeyAuth: [] }],
|
||||||
|
tags: [
|
||||||
|
{ name: "Agents", description: "Agent management" },
|
||||||
|
{ name: "Databases", description: "Database management and backup operations" },
|
||||||
|
],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user