* feat: background doctor operation * refactor(repo-details): design layout * refactor(doctor): support abort signal in all operations * chore: fix linting issue * chore: pr feedbacks * chore: merge conflicts * refactor: handle aborted signal in all operations * chore: pr feedbacks * chore: remove old migration
160 lines
3.9 KiB
TypeScript
160 lines
3.9 KiB
TypeScript
import { type } from "arktype";
|
|
|
|
export const REPOSITORY_BACKENDS = {
|
|
local: "local",
|
|
s3: "s3",
|
|
r2: "r2",
|
|
gcs: "gcs",
|
|
azure: "azure",
|
|
rclone: "rclone",
|
|
rest: "rest",
|
|
sftp: "sftp",
|
|
} as const;
|
|
|
|
export type RepositoryBackend = keyof typeof REPOSITORY_BACKENDS;
|
|
|
|
export const BANDWIDTH_UNITS = {
|
|
Kbps: "Kbps",
|
|
Mbps: "Mbps",
|
|
Gbps: "Gbps",
|
|
} as const;
|
|
|
|
export type BandwidthUnit = keyof typeof BANDWIDTH_UNITS;
|
|
|
|
export const bandwidthLimitSchema = type({
|
|
enabled: "boolean = false",
|
|
value: "number > 0 = 1",
|
|
unit: type.valueOf(BANDWIDTH_UNITS).default("Mbps"),
|
|
});
|
|
|
|
export type BandwidthLimit = typeof bandwidthLimitSchema.infer;
|
|
|
|
// Common fields for all repository configs
|
|
const baseRepositoryConfigSchema = type({
|
|
isExistingRepository: "boolean?",
|
|
customPassword: "string?",
|
|
cacert: "string?",
|
|
insecureTls: "boolean?",
|
|
// Bandwidth controls
|
|
uploadLimit: bandwidthLimitSchema.optional(),
|
|
downloadLimit: bandwidthLimitSchema.optional(),
|
|
});
|
|
|
|
export const s3RepositoryConfigSchema = type({
|
|
backend: "'s3'",
|
|
endpoint: "string",
|
|
bucket: "string",
|
|
accessKeyId: "string",
|
|
secretAccessKey: "string",
|
|
}).and(baseRepositoryConfigSchema);
|
|
|
|
export const r2RepositoryConfigSchema = type({
|
|
backend: "'r2'",
|
|
endpoint: "string",
|
|
bucket: "string",
|
|
accessKeyId: "string",
|
|
secretAccessKey: "string",
|
|
}).and(baseRepositoryConfigSchema);
|
|
|
|
export const localRepositoryConfigSchema = type({
|
|
backend: "'local'",
|
|
name: "string",
|
|
path: "string?",
|
|
}).and(baseRepositoryConfigSchema);
|
|
|
|
export const gcsRepositoryConfigSchema = type({
|
|
backend: "'gcs'",
|
|
bucket: "string",
|
|
projectId: "string",
|
|
credentialsJson: "string",
|
|
}).and(baseRepositoryConfigSchema);
|
|
|
|
export const azureRepositoryConfigSchema = type({
|
|
backend: "'azure'",
|
|
container: "string",
|
|
accountName: "string",
|
|
accountKey: "string",
|
|
endpointSuffix: "string?",
|
|
}).and(baseRepositoryConfigSchema);
|
|
|
|
export const rcloneRepositoryConfigSchema = type({
|
|
backend: "'rclone'",
|
|
remote: "string",
|
|
path: "string",
|
|
}).and(baseRepositoryConfigSchema);
|
|
|
|
export const restRepositoryConfigSchema = type({
|
|
backend: "'rest'",
|
|
url: "string",
|
|
username: "string?",
|
|
password: "string?",
|
|
path: "string?",
|
|
}).and(baseRepositoryConfigSchema);
|
|
|
|
export const sftpRepositoryConfigSchema = type({
|
|
backend: "'sftp'",
|
|
host: "string",
|
|
port: type("string.integer").or(type("number")).to("1 <= number <= 65535").default(22),
|
|
user: "string",
|
|
path: "string",
|
|
privateKey: "string",
|
|
skipHostKeyCheck: "boolean = true",
|
|
knownHosts: "string?",
|
|
}).and(baseRepositoryConfigSchema);
|
|
|
|
export const repositoryConfigSchemaBase = s3RepositoryConfigSchema
|
|
.or(r2RepositoryConfigSchema)
|
|
.or(localRepositoryConfigSchema)
|
|
.or(gcsRepositoryConfigSchema)
|
|
.or(azureRepositoryConfigSchema)
|
|
.or(rcloneRepositoryConfigSchema)
|
|
.or(restRepositoryConfigSchema)
|
|
.or(sftpRepositoryConfigSchema);
|
|
|
|
export const repositoryConfigSchema = repositoryConfigSchemaBase.onUndeclaredKey("delete");
|
|
|
|
export type RepositoryConfig = typeof repositoryConfigSchema.infer;
|
|
|
|
export const COMPRESSION_MODES = {
|
|
off: "off",
|
|
auto: "auto",
|
|
max: "max",
|
|
} as const;
|
|
|
|
export type CompressionMode = keyof typeof COMPRESSION_MODES;
|
|
|
|
export const REPOSITORY_STATUS = {
|
|
healthy: "healthy",
|
|
error: "error",
|
|
unknown: "unknown",
|
|
doctor: "doctor",
|
|
cancelled: "cancelled",
|
|
} as const;
|
|
|
|
export type RepositoryStatus = keyof typeof REPOSITORY_STATUS;
|
|
|
|
export const doctorStepSchema = type({
|
|
step: "string",
|
|
success: "boolean",
|
|
output: "string | null",
|
|
error: "string | null",
|
|
});
|
|
|
|
export type DoctorStep = typeof doctorStepSchema.infer;
|
|
|
|
export const doctorResultSchema = type({
|
|
success: "boolean",
|
|
steps: doctorStepSchema.array(),
|
|
completedAt: "number",
|
|
});
|
|
|
|
export type DoctorResult = typeof doctorResultSchema.infer;
|
|
|
|
export const OVERWRITE_MODES = {
|
|
always: "always",
|
|
ifChanged: "if-changed",
|
|
ifNewer: "if-newer",
|
|
never: "never",
|
|
} as const;
|
|
|
|
export type OverwriteMode = (typeof OVERWRITE_MODES)[keyof typeof OVERWRITE_MODES];
|