mirror of
https://github.com/nicotsx/ironmount.git
synced 2025-12-10 12:10:51 +01:00
refactor: simplify dtos and improve type saftey in json returns
This commit is contained in:
@@ -4,22 +4,23 @@ import {
|
||||
createVolumeBody,
|
||||
createVolumeDto,
|
||||
deleteVolumeDto,
|
||||
type GetVolumeResponseDto,
|
||||
getContainersDto,
|
||||
getVolumeDto,
|
||||
healthCheckDto,
|
||||
type ListContainersResponseDto,
|
||||
type ListFilesResponseDto,
|
||||
type ListVolumesResponseDto,
|
||||
type ListVolumesDto,
|
||||
listFilesDto,
|
||||
listVolumesDto,
|
||||
mountVolumeDto,
|
||||
testConnectionBody,
|
||||
testConnectionDto,
|
||||
type UpdateVolumeResponseDto,
|
||||
unmountVolumeDto,
|
||||
updateVolumeBody,
|
||||
updateVolumeDto,
|
||||
type CreateVolumeDto,
|
||||
type GetVolumeDto,
|
||||
type ListContainersDto,
|
||||
type UpdateVolumeDto,
|
||||
type ListFilesDto,
|
||||
} from "./volume.dto";
|
||||
import { volumeService } from "./volume.service";
|
||||
import { getVolumePath } from "./helpers";
|
||||
@@ -32,19 +33,21 @@ export const volumeController = new Hono()
|
||||
volumes: volumes.map((volume) => ({
|
||||
path: getVolumePath(volume.name),
|
||||
...volume,
|
||||
updatedAt: volume.updatedAt.getTime(),
|
||||
createdAt: volume.createdAt.getTime(),
|
||||
lastHealthCheck: volume.lastHealthCheck.getTime(),
|
||||
})),
|
||||
} satisfies ListVolumesResponseDto;
|
||||
};
|
||||
|
||||
return c.json(response, 200);
|
||||
return c.json<ListVolumesDto>(response, 200);
|
||||
})
|
||||
.post("/", createVolumeDto, validator("json", createVolumeBody), async (c) => {
|
||||
const body = c.req.valid("json");
|
||||
const res = await volumeService.createVolume(body.name, body.config);
|
||||
|
||||
return c.json({ message: "Volume created", volume: res.volume }, 201);
|
||||
const response = {
|
||||
...res.volume,
|
||||
path: getVolumePath(res.volume.name),
|
||||
};
|
||||
|
||||
return c.json<CreateVolumeDto>(response, 201);
|
||||
})
|
||||
.post("/test-connection", testConnectionDto, validator("json", testConnectionBody), async (c) => {
|
||||
const body = c.req.valid("json");
|
||||
@@ -66,28 +69,21 @@ export const volumeController = new Hono()
|
||||
volume: {
|
||||
...res.volume,
|
||||
path: getVolumePath(res.volume.name),
|
||||
createdAt: res.volume.createdAt.getTime(),
|
||||
updatedAt: res.volume.updatedAt.getTime(),
|
||||
lastHealthCheck: res.volume.lastHealthCheck.getTime(),
|
||||
},
|
||||
statfs: {
|
||||
total: res.statfs.total ?? 0,
|
||||
used: res.statfs.used ?? 0,
|
||||
free: res.statfs.free ?? 0,
|
||||
},
|
||||
} satisfies GetVolumeResponseDto;
|
||||
};
|
||||
|
||||
return c.json(response, 200);
|
||||
return c.json<GetVolumeDto>(response, 200);
|
||||
})
|
||||
.get("/:name/containers", getContainersDto, async (c) => {
|
||||
const { name } = c.req.param();
|
||||
const { containers } = await volumeService.getContainersUsingVolume(name);
|
||||
|
||||
const response = {
|
||||
containers,
|
||||
} satisfies ListContainersResponseDto;
|
||||
|
||||
return c.json(response, 200);
|
||||
return c.json<ListContainersDto>(containers, 200);
|
||||
})
|
||||
.put("/:name", updateVolumeDto, validator("json", updateVolumeBody), async (c) => {
|
||||
const { name } = c.req.param();
|
||||
@@ -95,17 +91,11 @@ export const volumeController = new Hono()
|
||||
const res = await volumeService.updateVolume(name, body);
|
||||
|
||||
const response = {
|
||||
message: "Volume updated",
|
||||
volume: {
|
||||
...res.volume,
|
||||
path: getVolumePath(res.volume.name),
|
||||
createdAt: res.volume.createdAt.getTime(),
|
||||
updatedAt: res.volume.updatedAt.getTime(),
|
||||
lastHealthCheck: res.volume.lastHealthCheck.getTime(),
|
||||
},
|
||||
} satisfies UpdateVolumeResponseDto;
|
||||
...res.volume,
|
||||
path: getVolumePath(res.volume.name),
|
||||
};
|
||||
|
||||
return c.json(response, 200);
|
||||
return c.json<UpdateVolumeDto>(response, 200);
|
||||
})
|
||||
.post("/:name/mount", mountVolumeDto, async (c) => {
|
||||
const { name } = c.req.param();
|
||||
@@ -133,9 +123,9 @@ export const volumeController = new Hono()
|
||||
const response = {
|
||||
files: result.files,
|
||||
path: result.path,
|
||||
} satisfies ListFilesResponseDto;
|
||||
};
|
||||
|
||||
c.header("Cache-Control", "public, max-age=10, stale-while-revalidate=60");
|
||||
|
||||
return c.json(response, 200);
|
||||
return c.json<ListFilesDto>(response, 200);
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ export type VolumeDto = typeof volumeSchema.infer;
|
||||
export const listVolumesResponse = type({
|
||||
volumes: volumeSchema.array(),
|
||||
});
|
||||
export type ListVolumesResponseDto = typeof listVolumesResponse.infer;
|
||||
export type ListVolumesDto = typeof listVolumesResponse.infer;
|
||||
|
||||
export const listVolumesDto = describeRoute({
|
||||
description: "List all volumes",
|
||||
@@ -50,13 +50,8 @@ export const createVolumeBody = type({
|
||||
config: volumeConfigSchema,
|
||||
});
|
||||
|
||||
export const createVolumeResponse = type({
|
||||
message: "string",
|
||||
volume: type({
|
||||
name: "string",
|
||||
path: "string",
|
||||
}),
|
||||
});
|
||||
export const createVolumeResponse = volumeSchema;
|
||||
export type CreateVolumeDto = typeof createVolumeResponse.infer;
|
||||
|
||||
export const createVolumeDto = describeRoute({
|
||||
description: "Create a new volume",
|
||||
@@ -80,6 +75,7 @@ export const createVolumeDto = describeRoute({
|
||||
export const deleteVolumeResponse = type({
|
||||
message: "string",
|
||||
});
|
||||
export type DeleteVolumeDto = typeof deleteVolumeResponse.infer;
|
||||
|
||||
export const deleteVolumeDto = describeRoute({
|
||||
description: "Delete a volume",
|
||||
@@ -108,7 +104,7 @@ const getVolumeResponse = type({
|
||||
statfs: statfsSchema,
|
||||
});
|
||||
|
||||
export type GetVolumeResponseDto = typeof getVolumeResponse.infer;
|
||||
export type GetVolumeDto = typeof getVolumeResponse.infer;
|
||||
/**
|
||||
* Get a volume
|
||||
*/
|
||||
@@ -141,10 +137,8 @@ export const updateVolumeBody = type({
|
||||
|
||||
export type UpdateVolumeBody = typeof updateVolumeBody.infer;
|
||||
|
||||
export const updateVolumeResponse = type({
|
||||
message: "string",
|
||||
volume: volumeSchema,
|
||||
});
|
||||
export const updateVolumeResponse = volumeSchema;
|
||||
export type UpdateVolumeDto = typeof updateVolumeResponse.infer;
|
||||
|
||||
export const updateVolumeDto = describeRoute({
|
||||
description: "Update a volume's configuration",
|
||||
@@ -165,8 +159,6 @@ export const updateVolumeDto = describeRoute({
|
||||
},
|
||||
});
|
||||
|
||||
export type UpdateVolumeResponseDto = typeof updateVolumeResponse.infer;
|
||||
|
||||
/**
|
||||
* Test connection
|
||||
*/
|
||||
@@ -178,6 +170,7 @@ export const testConnectionResponse = type({
|
||||
success: "boolean",
|
||||
message: "string",
|
||||
});
|
||||
export type TestConnectionDto = typeof testConnectionResponse.infer;
|
||||
|
||||
export const testConnectionDto = describeRoute({
|
||||
description: "Test connection to backend",
|
||||
@@ -202,6 +195,7 @@ 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",
|
||||
@@ -216,9 +210,6 @@ export const mountVolumeDto = describeRoute({
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "Volume not found",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -229,6 +220,7 @@ 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",
|
||||
@@ -243,9 +235,6 @@ export const unmountVolumeDto = describeRoute({
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "Volume not found",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -253,6 +242,7 @@ 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",
|
||||
@@ -283,10 +273,8 @@ const containerSchema = type({
|
||||
image: "string",
|
||||
});
|
||||
|
||||
export const listContainersResponse = type({
|
||||
containers: containerSchema.array(),
|
||||
});
|
||||
export type ListContainersResponseDto = typeof listContainersResponse.infer;
|
||||
export const listContainersResponse = containerSchema.array();
|
||||
export type ListContainersDto = typeof listContainersResponse.infer;
|
||||
|
||||
export const getContainersDto = describeRoute({
|
||||
description: "Get containers using a volume by name",
|
||||
@@ -322,7 +310,7 @@ export const listFilesResponse = type({
|
||||
files: fileEntrySchema.array(),
|
||||
path: "string",
|
||||
});
|
||||
export type ListFilesResponseDto = typeof listFilesResponse.infer;
|
||||
export type ListFilesDto = typeof listFilesResponse.infer;
|
||||
|
||||
export const listFilesDto = describeRoute({
|
||||
description: "List files in a volume directory",
|
||||
@@ -348,8 +336,5 @@ export const listFilesDto = describeRoute({
|
||||
},
|
||||
},
|
||||
},
|
||||
404: {
|
||||
description: "Volume not found",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -6,7 +6,6 @@ import Docker from "dockerode";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { ConflictError, InternalServerError, NotFoundError } from "http-errors-enhanced";
|
||||
import slugify from "slugify";
|
||||
import { VOLUME_MOUNT_BASE } from "../../core/constants";
|
||||
import { db } from "../../db/db";
|
||||
import { volumesTable } from "../../db/schema";
|
||||
import { toMessage } from "../../utils/errors";
|
||||
@@ -51,7 +50,7 @@ const createVolume = async (name: string, backendConfig: BackendConfig) => {
|
||||
|
||||
await db
|
||||
.update(volumesTable)
|
||||
.set({ status, lastError: error ?? null, lastHealthCheck: new Date() })
|
||||
.set({ status, lastError: error ?? null, lastHealthCheck: Date.now() })
|
||||
.where(eq(volumesTable.name, slug));
|
||||
|
||||
return { volume: created, status: 201 };
|
||||
@@ -85,7 +84,7 @@ const mountVolume = async (name: string) => {
|
||||
|
||||
await db
|
||||
.update(volumesTable)
|
||||
.set({ status, lastError: error ?? null, lastHealthCheck: new Date() })
|
||||
.set({ status, lastError: error ?? null, lastHealthCheck: Date.now() })
|
||||
.where(eq(volumesTable.name, name));
|
||||
|
||||
return { error, status };
|
||||
@@ -149,7 +148,7 @@ const updateVolume = async (name: string, volumeData: UpdateVolumeBody) => {
|
||||
config: volumeData.config,
|
||||
type: volumeData.config?.backend,
|
||||
autoRemount: volumeData.autoRemount,
|
||||
updatedAt: new Date(),
|
||||
updatedAt: Date.now(),
|
||||
})
|
||||
.where(eq(volumesTable.name, name))
|
||||
.returning();
|
||||
@@ -163,7 +162,7 @@ const updateVolume = async (name: string, volumeData: UpdateVolumeBody) => {
|
||||
const { error, status } = await backend.mount();
|
||||
await db
|
||||
.update(volumesTable)
|
||||
.set({ status, lastError: error ?? null, lastHealthCheck: new Date() })
|
||||
.set({ status, lastError: error ?? null, lastHealthCheck: Date.now() })
|
||||
.where(eq(volumesTable.name, name));
|
||||
}
|
||||
|
||||
@@ -178,9 +177,9 @@ const testConnection = async (backendConfig: BackendConfig) => {
|
||||
name: "test-connection",
|
||||
path: tempDir,
|
||||
config: backendConfig,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
lastHealthCheck: new Date(),
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
lastHealthCheck: Date.now(),
|
||||
type: backendConfig.backend,
|
||||
status: "unmounted" as const,
|
||||
lastError: null,
|
||||
@@ -215,7 +214,7 @@ const checkHealth = async (name: string) => {
|
||||
|
||||
await db
|
||||
.update(volumesTable)
|
||||
.set({ lastHealthCheck: new Date(), status, lastError: error ?? null })
|
||||
.set({ lastHealthCheck: Date.now(), status, lastError: error ?? null })
|
||||
.where(eq(volumesTable.name, volume.name));
|
||||
|
||||
return { status, error };
|
||||
|
||||
Reference in New Issue
Block a user