fix(api): согласовать задачу выпуска с контрактом сертификатов
This commit is contained in:
1 parent
594e60a1f4
commit
1d50ec8d17
8 files changed
+62
-16
No files matched your search
@@ -30,7 +30,7 @@
|
||||
"test:geoip": "tsx src/services/traffic-flow-geoip.test.ts",
|
||||
"test:ospf-optimizer": "tsx src/services/ospf-optimizer-identity.test.ts && tsx src/services/ospf-optimizer-metrics.test.ts && tsx src/services/ospf-optimizer-plan.test.ts && tsx src/routes/ospf-optimizer.test.ts",
|
||||
"test:containers": "tsx src/services/containers-state.test.ts && tsx src/routes/containers-state.test.ts",
|
||||
"test:certificates": "tsx src/services/certificate-parse.test.ts && tsx src/services/certificates-state.test.ts && tsx src/routes/certificates-state.test.ts"
|
||||
"test:certificates": "tsx src/services/certificate-issue-dto.test.ts && tsx src/services/certificate-parse.test.ts && tsx src/services/certificates-state.test.ts && tsx src/routes/certificates-state.test.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.888.0",
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import assert from "node:assert/strict"
|
||||
import { test } from "node:test"
|
||||
import type { CertificateIssueJobRow } from "../db/schema.js"
|
||||
import { mapCertificateIssueJob } from "./certificate-issue-dto.js"
|
||||
|
||||
const row: CertificateIssueJobRow = { id: "job-1", serverId: 1, status: "queued", step: "queued", source: "manual", certName: "cert", domainNames: ["test.example"], keyType: "rsa2048", trustStore: "www,api", requestedAt: "2026-10-01T00:00:00Z", startedAt: null, finishedAt: null, error: null }
|
||||
test("numeric DB server ID becomes string without altering job target", () => {
|
||||
const dto = mapCertificateIssueJob(row)
|
||||
assert.equal(dto.serverId, "1"); assert.deepEqual(dto.domainNames, ["test.example"]); assert.equal(dto.status, "queued")
|
||||
assert.equal(dto.startedAt, undefined); assert.equal(dto.error, undefined)
|
||||
})
|
||||
test("real failed runner step and error survive strict contract", () => {
|
||||
const dto = mapCertificateIssueJob({ ...row, status: "failed", step: "failed", error: "RouterOS import failed", finishedAt: "2026-10-01T00:01:00Z" })
|
||||
assert.equal(dto.status, "failed"); assert.equal(dto.step, "failed"); assert.equal(dto.error, "RouterOS import failed")
|
||||
})
|
||||
test("legacy JSON domains and done job remain compatible", () => {
|
||||
const dto = mapCertificateIssueJob({ ...row, status: "done", step: "done", domainNames: JSON.stringify(["test.example"]) })
|
||||
assert.deepEqual(dto.domainNames, ["test.example"]); assert.equal(dto.status, "done")
|
||||
})
|
||||
test("invalid state and malformed domain values do not become successful DTOs", () => {
|
||||
assert.throws(() => mapCertificateIssueJob({ ...row, step: "unexpected" }))
|
||||
assert.throws(() => mapCertificateIssueJob({ ...row, domainNames: [null] }))
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
import { certificateIssueJobSchema } from "@mmapp/contracts/certificates"
|
||||
import type { CertificateIssueJobRow } from "../db/schema.js"
|
||||
import { parseJsonArray } from "../db/json.js"
|
||||
|
||||
/** PostgreSQL server ID is numeric; HTTP contracts use a string identifier. */
|
||||
export function mapCertificateIssueJob(row: CertificateIssueJobRow) {
|
||||
return certificateIssueJobSchema.parse({
|
||||
id: row.id,
|
||||
status: row.status,
|
||||
step: row.step,
|
||||
serverId: String(row.serverId),
|
||||
certName: row.certName,
|
||||
domainNames: parseJsonArray(row.domainNames),
|
||||
requestedAt: row.requestedAt,
|
||||
startedAt: row.startedAt ?? undefined,
|
||||
finishedAt: row.finishedAt ?? undefined,
|
||||
error: row.error ?? undefined,
|
||||
})
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
certificateRenewSettings,
|
||||
servers,
|
||||
} from "../db/schema.js"
|
||||
import { mapCertificateIssueJob } from "./certificate-issue-dto.js"
|
||||
import { mapRosCertificates } from "./certificate-parse.js"
|
||||
import { MikrotikClient } from "./mikrotik.js"
|
||||
|
||||
@@ -158,19 +159,7 @@ export async function getIssueJobRecord(id: string) {
|
||||
}
|
||||
|
||||
export function toIssueJobDto(row: NonNullable<Awaited<ReturnType<typeof getIssueJobRecord>>>) {
|
||||
const domainNames = parseJsonArray(row.domainNames).map(String)
|
||||
return {
|
||||
id: row.id,
|
||||
status: row.status,
|
||||
step: row.step as "queued" | "acme_order" | "dns_challenge" | "finalize" | "import" | "cleanup" | "done",
|
||||
serverId: row.serverId,
|
||||
certName: row.certName,
|
||||
domainNames,
|
||||
requestedAt: row.requestedAt,
|
||||
startedAt: row.startedAt ?? undefined,
|
||||
finishedAt: row.finishedAt ?? undefined,
|
||||
error: row.error ?? undefined,
|
||||
}
|
||||
return mapCertificateIssueJob(row)
|
||||
}
|
||||
|
||||
export async function getServerRowByIdString(serverId: string | number) {
|
||||
|
||||
Reference in new issue
Block a user