Files
order_site/apps/backend/src/services/admin/write-helpers.ts
T

76 lines
2.0 KiB
TypeScript

import { buildClaimUrl, createTaskClaimToken } from '../claim/claim-service.js'
import {
maskCode as maskCodeValue,
maskPhone as maskPhoneValue,
} from '../../utils/masking.js'
import type { TaskRow } from '../../types/repository/rows.js'
type TaskClaimLink = {
token: string
expiredAt: string | null
claimUrl: string
}
type ErrorLike = {
errorCode?: string
code?: string
}
export function maskPhone(value: unknown): string {
return maskPhoneValue(value)
}
export function maskCode(value: unknown): string {
return maskCodeValue(value)
}
export function isRecoverableTaskSessionCloseError(error: ErrorLike | null | undefined): boolean {
const errorCode = String(error?.errorCode || error?.code || '').trim()
return errorCode === 'session_not_found' || errorCode === 'session_closed'
}
export function normalizeManualDispatchOutcome(value: unknown): 'delivered' | 'failed' {
const normalized = String(value || '').trim().toLowerCase()
if (normalized === 'failed') {
return 'failed'
}
return 'delivered'
}
export function getTaskClaimExpiresAt(task: Partial<TaskRow> | null | undefined): string | null {
return task?.claim_expires_at || task?.primary_claim_expires_at || null
}
export async function ensureTaskClaimLink(task: TaskRow): Promise<TaskClaimLink> {
const tokenStatus = String(task?.primary_claim_token_status || '').trim()
const token = String(task?.primary_claim_token || task?.claim_token || '').trim()
const expiredAt = getTaskClaimExpiresAt(task)
if (tokenStatus === 'active' && token && !isClaimExpired(expiredAt)) {
return {
token,
expiredAt,
claimUrl: buildClaimUrl(token),
}
}
const claimToken = await createTaskClaimToken(task.id)
return {
token: claimToken.token,
expiredAt: claimToken.expired_at,
claimUrl: claimToken.claimUrl,
}
}
function isClaimExpired(expiredAt: string | null): boolean {
if (!expiredAt) {
return false
}
const timestamp = new Date(expiredAt).getTime()
return Number.isFinite(timestamp) && timestamp <= Date.now()
}