mirror of
https://github.com/nicotsx/ironmount.git
synced 2025-12-10 12:10:51 +01:00
refactor: use schema constants
This commit is contained in:
1
apps/server/drizzle/0007_watery_sersi.sql
Normal file
1
apps/server/drizzle/0007_watery_sersi.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE `repositories_table` RENAME COLUMN "backend" TO "type";
|
||||
313
apps/server/drizzle/meta/0007_snapshot.json
Normal file
313
apps/server/drizzle/meta/0007_snapshot.json
Normal file
@@ -0,0 +1,313 @@
|
||||
{
|
||||
"version": "6",
|
||||
"dialect": "sqlite",
|
||||
"id": "866b1d3b-454b-4cf7-9835-a0f60d048b6e",
|
||||
"prevId": "16f360b6-fb61-44f3-a7f7-2bae78ebf7ca",
|
||||
"tables": {
|
||||
"repositories_table": {
|
||||
"name": "repositories_table",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"config": {
|
||||
"name": "config",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"compression_mode": {
|
||||
"name": "compression_mode",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": "'auto'"
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false,
|
||||
"default": "'unknown'"
|
||||
},
|
||||
"last_checked": {
|
||||
"name": "last_checked",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"last_error": {
|
||||
"name": "last_error",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch())"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch())"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"repositories_table_name_unique": {
|
||||
"name": "repositories_table_name_unique",
|
||||
"columns": [
|
||||
"name"
|
||||
],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"sessions_table": {
|
||||
"name": "sessions_table",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"user_id": {
|
||||
"name": "user_id",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"expires_at": {
|
||||
"name": "expires_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch())"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"sessions_table_user_id_users_table_id_fk": {
|
||||
"name": "sessions_table_user_id_users_table_id_fk",
|
||||
"tableFrom": "sessions_table",
|
||||
"tableTo": "users_table",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"users_table": {
|
||||
"name": "users_table",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"username": {
|
||||
"name": "username",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"password_hash": {
|
||||
"name": "password_hash",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch())"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch())"
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"users_table_username_unique": {
|
||||
"name": "users_table_username_unique",
|
||||
"columns": [
|
||||
"username"
|
||||
],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
},
|
||||
"volumes_table": {
|
||||
"name": "volumes_table",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "integer",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "'unmounted'"
|
||||
},
|
||||
"last_error": {
|
||||
"name": "last_error",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"last_health_check": {
|
||||
"name": "last_health_check",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch())"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch())"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "(unixepoch())"
|
||||
},
|
||||
"config": {
|
||||
"name": "config",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"auto_remount": {
|
||||
"name": "auto_remount",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"volumes_table_name_unique": {
|
||||
"name": "volumes_table_name_unique",
|
||||
"columns": [
|
||||
"name"
|
||||
],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"checkConstraints": {}
|
||||
}
|
||||
},
|
||||
"views": {},
|
||||
"enums": {},
|
||||
"_meta": {
|
||||
"schemas": {},
|
||||
"tables": {},
|
||||
"columns": {
|
||||
"\"repositories_table\".\"backend\"": "\"repositories_table\".\"type\""
|
||||
}
|
||||
},
|
||||
"internal": {
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,13 @@
|
||||
"when": 1760734377440,
|
||||
"tag": "0006_secret_micromacro",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"version": "6",
|
||||
"when": 1761224911352,
|
||||
"tag": "0007_watery_sersi",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -9,11 +9,10 @@
|
||||
"studio": "drizzle-kit studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hono/arktype-validator": "^2.0.1",
|
||||
"@hono/standard-validator": "^0.1.5",
|
||||
"@ironmount/schemas": "workspace:*",
|
||||
"@scalar/hono-api-reference": "^0.9.13",
|
||||
"arktype": "^2.1.20",
|
||||
"arktype": "^2.1.23",
|
||||
"dockerode": "^4.0.8",
|
||||
"dotenv": "^17.2.1",
|
||||
"drizzle-orm": "^0.44.6",
|
||||
|
||||
@@ -47,7 +47,7 @@ export type Session = typeof sessionsTable.$inferSelect;
|
||||
export const repositoriesTable = sqliteTable("repositories_table", {
|
||||
id: text().primaryKey(),
|
||||
name: text().notNull().unique(),
|
||||
backend: text().$type<RepositoryBackend>().notNull(),
|
||||
type: text().$type<RepositoryBackend>().notNull(),
|
||||
config: text("config", { mode: "json" }).$type<typeof repositoryConfigSchema.inferOut>().notNull(),
|
||||
compressionMode: text("compression_mode").$type<CompressionMode>().default("auto"),
|
||||
status: text().$type<RepositoryStatus>().default("unknown"),
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
import { repositoryConfigSchema } from "@ironmount/schemas/restic";
|
||||
import {
|
||||
COMPRESSION_MODES,
|
||||
REPOSITORY_BACKENDS,
|
||||
REPOSITORY_STATUS,
|
||||
repositoryConfigSchema,
|
||||
} from "@ironmount/schemas/restic";
|
||||
import { type } from "arktype";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
const repositorySchema = type({
|
||||
id: "string",
|
||||
name: "string",
|
||||
backend: type.enumerated("local", "sftp", "s3"),
|
||||
type: type.valueOf(REPOSITORY_BACKENDS),
|
||||
config: repositoryConfigSchema,
|
||||
compressionMode: type.enumerated("off", "auto", "fastest", "better", "max").or("null"),
|
||||
status: type.enumerated("healthy", "error", "unknown").or("null"),
|
||||
compressionMode: type.valueOf(COMPRESSION_MODES).or("null"),
|
||||
status: type.valueOf(REPOSITORY_STATUS).or("null"),
|
||||
lastChecked: "number | null",
|
||||
lastError: "string | null",
|
||||
createdAt: "number",
|
||||
@@ -46,8 +51,8 @@ export const listRepositoriesDto = describeRoute({
|
||||
*/
|
||||
export const createRepositoryBody = type({
|
||||
name: "string",
|
||||
compressionMode: type.valueOf(COMPRESSION_MODES).optional(),
|
||||
config: repositoryConfigSchema,
|
||||
"compressionMode?": type.enumerated("off", "auto", "fastest", "better", "max"),
|
||||
});
|
||||
|
||||
export type CreateRepositoryBody = typeof createRepositoryBody.infer;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import crypto from "node:crypto";
|
||||
import type { CompressionMode, RepositoryConfig } from "@ironmount/schemas";
|
||||
import type { CompressionMode, RepositoryConfig } from "@ironmount/schemas/restic";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { ConflictError, InternalServerError, NotFoundError } from "http-errors-enhanced";
|
||||
import slugify from "slugify";
|
||||
@@ -15,14 +15,16 @@ const listRepositories = async () => {
|
||||
};
|
||||
|
||||
const encryptConfig = async (config: RepositoryConfig): Promise<RepositoryConfig> => {
|
||||
const encryptedConfig = { ...config };
|
||||
const encryptedConfig: Record<string, string> = { ...config };
|
||||
|
||||
switch (config.backend) {
|
||||
case "s3":
|
||||
encryptedConfig.accessKeyId = await cryptoUtils.encrypt(config.accessKeyId);
|
||||
encryptedConfig.secretAccessKey = await cryptoUtils.encrypt(config.secretAccessKey);
|
||||
break;
|
||||
}
|
||||
return encryptedConfig;
|
||||
|
||||
return encryptedConfig as RepositoryConfig;
|
||||
};
|
||||
|
||||
const createRepository = async (name: string, config: RepositoryConfig, compressionMode?: CompressionMode) => {
|
||||
@@ -45,7 +47,7 @@ const createRepository = async (name: string, config: RepositoryConfig, compress
|
||||
.values({
|
||||
id,
|
||||
name: slug,
|
||||
backend: config.backend,
|
||||
type: config.backend,
|
||||
config: encryptedConfig,
|
||||
compressionMode: compressionMode ?? "auto",
|
||||
status: "unknown",
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { volumeConfigSchema } from "@ironmount/schemas";
|
||||
import { BACKEND_STATUS, BACKEND_TYPES, volumeConfigSchema } from "@ironmount/schemas";
|
||||
import { type } from "arktype";
|
||||
import { describeRoute, resolver } from "hono-openapi";
|
||||
|
||||
const volumeSchema = type({
|
||||
name: "string",
|
||||
path: "string",
|
||||
type: type.enumerated("nfs", "smb", "directory", "webdav"),
|
||||
status: type.enumerated("mounted", "unmounted", "error", "unknown"),
|
||||
type: type.valueOf(BACKEND_TYPES),
|
||||
status: type.valueOf(BACKEND_STATUS),
|
||||
lastError: "string | null",
|
||||
createdAt: "number",
|
||||
updatedAt: "number",
|
||||
@@ -199,7 +199,7 @@ export const testConnectionDto = describeRoute({
|
||||
*/
|
||||
export const mountVolumeResponse = type({
|
||||
error: "string?",
|
||||
status: type.enumerated("mounted", "unmounted", "error"),
|
||||
status: type.valueOf(BACKEND_STATUS),
|
||||
});
|
||||
|
||||
export const mountVolumeDto = describeRoute({
|
||||
@@ -226,7 +226,7 @@ export const mountVolumeDto = describeRoute({
|
||||
*/
|
||||
export const unmountVolumeResponse = type({
|
||||
error: "string?",
|
||||
status: type.enumerated("mounted", "unmounted", "error"),
|
||||
status: type.valueOf(BACKEND_STATUS),
|
||||
});
|
||||
|
||||
export const unmountVolumeDto = describeRoute({
|
||||
@@ -250,7 +250,7 @@ export const unmountVolumeDto = describeRoute({
|
||||
|
||||
export const healthCheckResponse = type({
|
||||
error: "string?",
|
||||
status: type.enumerated("mounted", "unmounted", "error"),
|
||||
status: type.valueOf(BACKEND_STATUS),
|
||||
});
|
||||
|
||||
export const healthCheckDto = describeRoute({
|
||||
|
||||
Reference in New Issue
Block a user