Files
ironmount/app/server/modules/volumes/volume.dto.ts
Nico 95a0d44b45 refactor: unify backend and frontend servers (#3)
* refactor: unify backend and frontend servers

* refactor: correct paths for openapi & drizzle

* refactor: move api-client to client

* fix: drizzle paths

* chore: fix linting issues

* fix: form reset issue
2025-11-13 20:11:46 +01:00

374 lines
7.6 KiB
TypeScript

import { type } from "arktype";
import { describeRoute, resolver } from "hono-openapi";
import { BACKEND_STATUS, BACKEND_TYPES, volumeConfigSchema } from "~/schemas/volumes";
export const volumeSchema = type({
id: "number",
name: "string",
type: type.valueOf(BACKEND_TYPES),
status: type.valueOf(BACKEND_STATUS),
lastError: "string | null",
createdAt: "number",
updatedAt: "number",
lastHealthCheck: "number",
config: volumeConfigSchema,
autoRemount: "boolean",
});
export type VolumeDto = typeof volumeSchema.infer;
/**
* List all volumes
*/
export const listVolumesResponse = volumeSchema.array();
export type ListVolumesDto = typeof listVolumesResponse.infer;
export const listVolumesDto = describeRoute({
description: "List all volumes",
tags: ["Volumes"],
operationId: "listVolumes",
responses: {
200: {
description: "A list of volumes",
content: {
"application/json": {
schema: resolver(listVolumesResponse),
},
},
},
},
});
/**
* Create a new volume
*/
export const createVolumeBody = type({
name: "string",
config: volumeConfigSchema,
});
export const createVolumeResponse = volumeSchema;
export type CreateVolumeDto = typeof createVolumeResponse.infer;
export const createVolumeDto = describeRoute({
description: "Create a new volume",
operationId: "createVolume",
tags: ["Volumes"],
responses: {
201: {
description: "Volume created successfully",
content: {
"application/json": {
schema: resolver(createVolumeResponse),
},
},
},
},
});
/**
* Delete a volume
*/
export const deleteVolumeResponse = type({
message: "string",
});
export type DeleteVolumeDto = typeof deleteVolumeResponse.infer;
export const deleteVolumeDto = describeRoute({
description: "Delete a volume",
operationId: "deleteVolume",
tags: ["Volumes"],
responses: {
200: {
description: "Volume deleted successfully",
content: {
"application/json": {
schema: resolver(deleteVolumeResponse),
},
},
},
},
});
const statfsSchema = type({
total: "number",
used: "number",
free: "number",
});
const getVolumeResponse = type({
volume: volumeSchema,
statfs: statfsSchema,
});
export type GetVolumeDto = typeof getVolumeResponse.infer;
/**
* Get a volume
*/
export const getVolumeDto = describeRoute({
description: "Get a volume by name",
operationId: "getVolume",
tags: ["Volumes"],
responses: {
200: {
description: "Volume details",
content: {
"application/json": {
schema: resolver(getVolumeResponse),
},
},
},
404: {
description: "Volume not found",
},
},
});
/**
* Update a volume
*/
export const updateVolumeBody = type({
autoRemount: "boolean?",
config: volumeConfigSchema.optional(),
});
export type UpdateVolumeBody = typeof updateVolumeBody.infer;
export const updateVolumeResponse = volumeSchema;
export type UpdateVolumeDto = typeof updateVolumeResponse.infer;
export const updateVolumeDto = describeRoute({
description: "Update a volume's configuration",
operationId: "updateVolume",
tags: ["Volumes"],
responses: {
200: {
description: "Volume updated successfully",
content: {
"application/json": {
schema: resolver(updateVolumeResponse),
},
},
},
404: {
description: "Volume not found",
},
},
});
/**
* Test connection
*/
export const testConnectionBody = type({
config: volumeConfigSchema,
});
export const testConnectionResponse = type({
success: "boolean",
message: "string",
});
export type TestConnectionDto = typeof testConnectionResponse.infer;
export const testConnectionDto = describeRoute({
description: "Test connection to backend",
operationId: "testConnection",
tags: ["Volumes"],
responses: {
200: {
description: "Connection test result",
content: {
"application/json": {
schema: resolver(testConnectionResponse),
},
},
},
},
});
/**
* Mount volume
*/
export const mountVolumeResponse = type({
error: "string?",
status: type.valueOf(BACKEND_STATUS),
});
export type MountVolumeDto = typeof mountVolumeResponse.infer;
export const mountVolumeDto = describeRoute({
description: "Mount a volume",
operationId: "mountVolume",
tags: ["Volumes"],
responses: {
200: {
description: "Volume mounted successfully",
content: {
"application/json": {
schema: resolver(mountVolumeResponse),
},
},
},
},
});
/**
* Unmount volume
*/
export const unmountVolumeResponse = type({
error: "string?",
status: type.valueOf(BACKEND_STATUS),
});
export type UnmountVolumeDto = typeof unmountVolumeResponse.infer;
export const unmountVolumeDto = describeRoute({
description: "Unmount a volume",
operationId: "unmountVolume",
tags: ["Volumes"],
responses: {
200: {
description: "Volume unmounted successfully",
content: {
"application/json": {
schema: resolver(unmountVolumeResponse),
},
},
},
},
});
export const healthCheckResponse = type({
error: "string?",
status: type.valueOf(BACKEND_STATUS),
});
export type HealthCheckDto = typeof healthCheckResponse.infer;
export const healthCheckDto = describeRoute({
description: "Perform a health check on a volume",
operationId: "healthCheckVolume",
tags: ["Volumes"],
responses: {
200: {
description: "Volume health check result",
content: {
"application/json": {
schema: resolver(healthCheckResponse),
},
},
},
404: {
description: "Volume not found",
},
},
});
/**
* Get containers using a volume
*/
const containerSchema = type({
id: "string",
name: "string",
state: "string",
image: "string",
});
export const listContainersResponse = containerSchema.array();
export type ListContainersDto = typeof listContainersResponse.infer;
export const getContainersDto = describeRoute({
description: "Get containers using a volume by name",
operationId: "getContainersUsingVolume",
tags: ["Volumes"],
responses: {
200: {
description: "List of containers using the volume",
content: {
"application/json": {
schema: resolver(listContainersResponse),
},
},
},
404: {
description: "Volume not found",
},
},
});
/**
* List files in a volume
*/
const fileEntrySchema = type({
name: "string",
path: "string",
type: type.enumerated("file", "directory"),
size: "number?",
modifiedAt: "number?",
});
export const listFilesResponse = type({
files: fileEntrySchema.array(),
path: "string",
});
export type ListFilesDto = typeof listFilesResponse.infer;
export const listFilesDto = describeRoute({
description: "List files in a volume directory",
operationId: "listFiles",
tags: ["Volumes"],
parameters: [
{
in: "query",
name: "path",
required: false,
schema: {
type: "string",
},
description: "Subdirectory path to list (relative to volume root)",
},
],
responses: {
200: {
description: "List of files in the volume",
content: {
"application/json": {
schema: resolver(listFilesResponse),
},
},
},
},
});
/**
* Browse filesystem directories
*/
export const browseFilesystemResponse = type({
directories: fileEntrySchema.array(),
path: "string",
});
export type BrowseFilesystemDto = typeof browseFilesystemResponse.infer;
export const browseFilesystemDto = describeRoute({
description: "Browse directories on the host filesystem",
operationId: "browseFilesystem",
tags: ["Volumes"],
parameters: [
{
in: "query",
name: "path",
required: false,
schema: {
type: "string",
},
description: "Directory path to browse (absolute path, defaults to /)",
},
],
responses: {
200: {
description: "List of directories in the specified path",
content: {
"application/json": {
schema: resolver(browseFilesystemResponse),
},
},
},
},
});