fix(backups): сохранять расписание и хранилище независимо
This commit is contained in:
1 parent
5ce21e9a47
commit
8e01666e0e
12 files changed
+286
-104
No files matched your search
@@ -0,0 +1,18 @@
|
||||
import assert from "node:assert/strict"
|
||||
import { test } from "node:test"
|
||||
import { backupSchedulePayload } from "./backup-settings"
|
||||
const form = { enabled: false, frequency: "daily" as const, hour: "0", minute: "7", weekDay: 0, monthDay: 1, keepCount: "365", format: "rsc" as const }
|
||||
test("schedule preserves zero, arbitrary minute and explicit all-enabled semantics", () => {
|
||||
const result = backupSchedulePayload(form, ["1"], true)
|
||||
assert.equal(result.hour, 0); assert.equal(result.minute, 7); assert.equal(result.keepCount, 365); assert.deepEqual(result.serverIds, [])
|
||||
assert.deepEqual(backupSchedulePayload(form, ["1"], false).serverIds, ["1"])
|
||||
})
|
||||
test("blank, fractional, negative and out-of-range numbers are rejected without normalization", () => {
|
||||
for (const hour of ["", "1.5", "-1", "24", "1e1"]) assert.throws(() => backupSchedulePayload({ ...form, hour }, ["1"], false))
|
||||
assert.throws(() => backupSchedulePayload({ ...form, keepCount: "366" }, ["1"], false))
|
||||
assert.throws(() => backupSchedulePayload(form, [], false))
|
||||
})
|
||||
test("unsupported binary schedule requires an explicit format choice", () => {
|
||||
assert.throws(() => backupSchedulePayload({ ...form, enabled: true, format: "backup" }, ["1"], false))
|
||||
assert.equal(backupSchedulePayload({ ...form, format: "backup" }, ["1"], false).format, "backup")
|
||||
})
|
||||
@@ -0,0 +1,17 @@
|
||||
import { putBackupScheduleSettingsSchema, putBackupStorageSettingsSchema } from "@mmapp/contracts/backups"
|
||||
import type { BackupScheduleForm, BackupStorageForm } from "@/components/backups/backups-settings"
|
||||
|
||||
function integer(value: number | string, label: string, min: number, max: number): number {
|
||||
if (!/^[0-9]+$/.test(String(value))) throw new Error(label + ": введите целое число")
|
||||
const number = Number(value)
|
||||
if (!Number.isSafeInteger(number) || number < min || number > max) throw new Error(label + ": допустимо от " + min + " до " + max)
|
||||
return number
|
||||
}
|
||||
export function backupSchedulePayload(form: BackupScheduleForm, serverIds: string[], allEnabled: boolean) {
|
||||
if (!allEnabled && !serverIds.length) throw new Error("Выберите серверы или режим всех включённых устройств")
|
||||
if (form.enabled && form.format !== "rsc") throw new Error("Плановый binary backup пока не поддерживается; выберите .rsc явно")
|
||||
return putBackupScheduleSettingsSchema.parse({ ...form, hour: integer(form.hour, "Час", 0, 23), minute: integer(form.minute, "Минута", 0, 59), weekDay: integer(form.weekDay, "День недели", 0, 6), monthDay: integer(form.monthDay, "День месяца", 1, 28), keepCount: integer(form.keepCount, "Число копий", 1, 365), serverIds: allEnabled ? [] : serverIds })
|
||||
}
|
||||
export function backupStoragePayload(form: BackupStorageForm) {
|
||||
return putBackupStorageSettingsSchema.parse({ provider: form.provider, s3Endpoint: form.s3Endpoint, s3Region: form.s3Region, s3Bucket: form.s3Bucket, s3Prefix: form.s3Prefix, s3AccessKeyId: form.s3AccessKeyId, s3SecretAccessKey: form.s3SecretAccessKey || undefined, s3ForcePathStyle: form.s3ForcePathStyle, keepLocalCopy: form.keepLocalCopy })
|
||||
}
|
||||
Reference in new issue
Block a user