开启后端严格空值检查
This commit is contained in:
@@ -19,7 +19,7 @@ router.get('/orders', createJsonHandler(
|
|||||||
))
|
))
|
||||||
|
|
||||||
router.get('/orders/:orderId', createJsonHandler(
|
router.get('/orders/:orderId', createJsonHandler(
|
||||||
(req) => getAdminOrderDetail((req.params as AdminOrderRouteParams).orderId),
|
(req) => getAdminOrderDetail(String((req.params as AdminOrderRouteParams).orderId || '')),
|
||||||
{
|
{
|
||||||
successMessage: 'ok',
|
successMessage: 'ok',
|
||||||
errorMessage: '读取订单详情失败',
|
errorMessage: '读取订单详情失败',
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ router.get(
|
|||||||
router.post(
|
router.post(
|
||||||
"/ninetyone/orders/:id/retry",
|
"/ninetyone/orders/:id/retry",
|
||||||
createJsonHandler(
|
createJsonHandler(
|
||||||
(req) => retryAdminNinetyoneOrder((req.params as AdminEntityRouteParams).id),
|
(req) => retryAdminNinetyoneOrder(String((req.params as AdminEntityRouteParams).id || "")),
|
||||||
{
|
{
|
||||||
successMessage: "91卡券订单已重试",
|
successMessage: "91卡券订单已重试",
|
||||||
errorMessage: "重试 91卡券订单失败",
|
errorMessage: "重试 91卡券订单失败",
|
||||||
@@ -49,7 +49,7 @@ router.post(
|
|||||||
createJsonHandler(
|
createJsonHandler(
|
||||||
(req) =>
|
(req) =>
|
||||||
failAdminNinetyoneOrder(
|
failAdminNinetyoneOrder(
|
||||||
(req.params as AdminEntityRouteParams).id,
|
String((req.params as AdminEntityRouteParams).id || ""),
|
||||||
req.body as { reason?: string }
|
req.body as { reason?: string }
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -73,6 +73,17 @@ export function requireAdminRoles(allowedRoles: string[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRequiredAdminSession(req: Request): AdminSession {
|
||||||
|
if (req.adminSession) {
|
||||||
|
return req.adminSession
|
||||||
|
}
|
||||||
|
|
||||||
|
throw createHttpError('未登录或登录已失效', {
|
||||||
|
statusCode: 401,
|
||||||
|
errorCode: 'admin_auth_required',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async function recordAdminAudit(
|
async function recordAdminAudit(
|
||||||
session: AdminSession | null | undefined,
|
session: AdminSession | null | undefined,
|
||||||
req: Request,
|
req: Request,
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ import type { AdminTaskActionResponse } from "../../types/admin-write-models.js"
|
|||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
function getTaskId(req: Request): string | undefined {
|
function getTaskId(req: Request): string {
|
||||||
return (req.params as AdminTaskRouteParams).taskId;
|
return String((req.params as AdminTaskRouteParams).taskId || "");
|
||||||
}
|
}
|
||||||
|
|
||||||
router.get(
|
router.get(
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
updateManagedAdminUserRole,
|
updateManagedAdminUserRole,
|
||||||
updateManagedAdminUserStatus,
|
updateManagedAdminUserStatus,
|
||||||
} from '../../services/admin/admin-auth-service.js'
|
} from '../../services/admin/admin-auth-service.js'
|
||||||
import { createJsonHandler, requireAdminRoles } from './shared.js'
|
import { createJsonHandler, getRequiredAdminSession, requireAdminRoles } from './shared.js'
|
||||||
|
|
||||||
type AdminUserMutationResult = {
|
type AdminUserMutationResult = {
|
||||||
user: {
|
user: {
|
||||||
@@ -54,7 +54,7 @@ router.post('/users', createJsonHandler(
|
|||||||
))
|
))
|
||||||
|
|
||||||
router.post('/users/:userId/role', createJsonHandler(
|
router.post('/users/:userId/role', createJsonHandler(
|
||||||
(req) => updateManagedAdminUserRole(String(req.params.userId), req.body, req.adminSession),
|
(req) => updateManagedAdminUserRole(String(req.params.userId || ''), req.body, getRequiredAdminSession(req)),
|
||||||
{
|
{
|
||||||
successMessage: '用户角色已更新',
|
successMessage: '用户角色已更新',
|
||||||
errorMessage: '更新用户角色失败',
|
errorMessage: '更新用户角色失败',
|
||||||
@@ -75,7 +75,7 @@ router.post('/users/:userId/role', createJsonHandler(
|
|||||||
))
|
))
|
||||||
|
|
||||||
router.post('/users/:userId/status', createJsonHandler(
|
router.post('/users/:userId/status', createJsonHandler(
|
||||||
(req) => updateManagedAdminUserStatus(String(req.params.userId), req.body, req.adminSession),
|
(req) => updateManagedAdminUserStatus(String(req.params.userId || ''), req.body, getRequiredAdminSession(req)),
|
||||||
{
|
{
|
||||||
successMessage: '用户状态已更新',
|
successMessage: '用户状态已更新',
|
||||||
errorMessage: '更新用户状态失败',
|
errorMessage: '更新用户状态失败',
|
||||||
@@ -96,7 +96,7 @@ router.post('/users/:userId/status', createJsonHandler(
|
|||||||
))
|
))
|
||||||
|
|
||||||
router.post('/users/:userId/reset-password', createJsonHandler(
|
router.post('/users/:userId/reset-password', createJsonHandler(
|
||||||
(req) => resetManagedAdminUserPassword(String(req.params.userId), req.body),
|
(req) => resetManagedAdminUserPassword(String(req.params.userId || ''), req.body),
|
||||||
{
|
{
|
||||||
successMessage: '用户密码已重置',
|
successMessage: '用户密码已重置',
|
||||||
errorMessage: '重置用户密码失败',
|
errorMessage: '重置用户密码失败',
|
||||||
|
|||||||
@@ -171,8 +171,8 @@ export async function getAdminSessionSummary(token: unknown): Promise<JsonObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function requireAdminRole(session: { role?: string }, allowedRoles: string[]): void {
|
export function requireAdminRole(session: { role?: string } | null | undefined, allowedRoles: string[]): void {
|
||||||
if (allowedRoles.includes(session.role)) {
|
if (session && allowedRoles.includes(session.role || '')) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,6 +236,12 @@ export async function createManagedAdminUser(payload: JsonObject = {}): Promise<
|
|||||||
createdAt: now,
|
createdAt: now,
|
||||||
updatedAt: now,
|
updatedAt: now,
|
||||||
})
|
})
|
||||||
|
if (!created) {
|
||||||
|
throw createHttpError('后台用户创建失败', {
|
||||||
|
statusCode: 500,
|
||||||
|
errorCode: 'admin_user_create_failed',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user: mapAdminUser(created),
|
user: mapAdminUser(created),
|
||||||
@@ -262,6 +268,12 @@ export async function updateManagedAdminUserRole(
|
|||||||
session_version: nextAdminSessionVersion(user),
|
session_version: nextAdminSessionVersion(user),
|
||||||
updated_at: nowIso(),
|
updated_at: nowIso(),
|
||||||
})
|
})
|
||||||
|
if (!updated) {
|
||||||
|
throw createHttpError('后台用户更新失败', {
|
||||||
|
statusCode: 500,
|
||||||
|
errorCode: 'admin_user_update_failed',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user: mapAdminUser(updated),
|
user: mapAdminUser(updated),
|
||||||
@@ -288,6 +300,12 @@ export async function updateManagedAdminUserStatus(
|
|||||||
session_version: nextAdminSessionVersion(user),
|
session_version: nextAdminSessionVersion(user),
|
||||||
updated_at: nowIso(),
|
updated_at: nowIso(),
|
||||||
})
|
})
|
||||||
|
if (!updated) {
|
||||||
|
throw createHttpError('后台用户更新失败', {
|
||||||
|
statusCode: 500,
|
||||||
|
errorCode: 'admin_user_update_failed',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user: mapAdminUser(updated),
|
user: mapAdminUser(updated),
|
||||||
@@ -311,6 +329,12 @@ export async function resetManagedAdminUserPassword(userId: number | string, pay
|
|||||||
session_version: nextAdminSessionVersion(user),
|
session_version: nextAdminSessionVersion(user),
|
||||||
updated_at: nowIso(),
|
updated_at: nowIso(),
|
||||||
})
|
})
|
||||||
|
if (!updated) {
|
||||||
|
throw createHttpError('后台用户更新失败', {
|
||||||
|
statusCode: 500,
|
||||||
|
errorCode: 'admin_user_update_failed',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user: mapAdminUser(updated),
|
user: mapAdminUser(updated),
|
||||||
@@ -490,7 +514,7 @@ async function ensureAdminUserChangeAllowed(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapAdminUser(user: AdminUserRow | null): JsonObject {
|
function mapAdminUser(user: AdminUserRow): JsonObject {
|
||||||
return {
|
return {
|
||||||
userId: Number(user.id),
|
userId: Number(user.id),
|
||||||
username: String(user.username || ''),
|
username: String(user.username || ''),
|
||||||
|
|||||||
@@ -158,9 +158,10 @@ export async function getAdminTaskDetail(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const primaryClaimTokenId = getTaskPrimaryClaimTokenId(task)
|
||||||
const [order, claimToken, taskEvents] = await Promise.all([
|
const [order, claimToken, taskEvents] = await Promise.all([
|
||||||
getOrderById(task.order_id),
|
getOrderById(task.order_id),
|
||||||
getTaskPrimaryClaimTokenId(task) ? getClaimTokenById(getTaskPrimaryClaimTokenId(task)) : Promise.resolve(null),
|
primaryClaimTokenId ? getClaimTokenById(primaryClaimTokenId) : Promise.resolve(null),
|
||||||
listTaskEventsByTaskId(task.id),
|
listTaskEventsByTaskId(task.id),
|
||||||
])
|
])
|
||||||
const orderItems = order ? await listOrderItemsByOrderId(order.id) : []
|
const orderItems = order ? await listOrderItemsByOrderId(order.id) : []
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ export function canRegenerateClaimLinkForViewer(task: TaskLike, viewerContext: A
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseAllowed = ['link_generated', 'claimed', 'role_confirmed', 'retry_pending', 'manual_review'].includes(task.task_status)
|
const baseAllowed = ['link_generated', 'claimed', 'role_confirmed', 'retry_pending', 'manual_review'].includes(String(task.task_status || '').trim())
|
||||||
|
|
||||||
if (!baseAllowed) {
|
if (!baseAllowed) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export function updateAdminCloudtentaclesSourceConfig(
|
|||||||
});
|
});
|
||||||
const saved = saveCloudtentaclesSourceByKey(sourceKey, normalized);
|
const saved = saveCloudtentaclesSourceByKey(sourceKey, normalized);
|
||||||
const shouldClearSession = hasCloudtentaclesCredentialContextChanged(
|
const shouldClearSession = hasCloudtentaclesCredentialContextChanged(
|
||||||
current,
|
current || undefined,
|
||||||
saved
|
saved
|
||||||
);
|
);
|
||||||
const session = shouldClearSession
|
const session = shouldClearSession
|
||||||
@@ -146,7 +146,7 @@ export function updateAdminCloudtentaclesSourceConfig(
|
|||||||
filePath: getCloudtentaclesSourcesFilePath(),
|
filePath: getCloudtentaclesSourcesFilePath(),
|
||||||
sessionFilePath: getCloudtentaclesSessionFilePath(),
|
sessionFilePath: getCloudtentaclesSessionFilePath(),
|
||||||
source: mapAdminCloudtentaclesSourceConfig(saved),
|
source: mapAdminCloudtentaclesSourceConfig(saved),
|
||||||
session: mapAdminCloudtentaclesSession(session),
|
session: mapAdminCloudtentaclesSession(session || undefined),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ async function expireClaimContext(claimToken: ClaimTokenRow, task: TaskRow) {
|
|||||||
user_action_status: 'expired',
|
user_action_status: 'expired',
|
||||||
last_error: '领取链接已过期',
|
last_error: '领取链接已过期',
|
||||||
updated_at: now,
|
updated_at: now,
|
||||||
})
|
}) || task
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ export async function getKuaishouCloudClaimDetail(token: unknown) {
|
|||||||
let task = context.task
|
let task = context.task
|
||||||
|
|
||||||
if (String(task.executor_key || '').trim() === 'kuaishou_ct_assisted') {
|
if (String(task.executor_key || '').trim() === 'kuaishou_ct_assisted') {
|
||||||
task = await syncKuaishouCloudRoleInfo(task)
|
task = await syncKuaishouCloudRoleInfo(task) || task
|
||||||
}
|
}
|
||||||
|
|
||||||
return buildClaimDetailPayload({
|
return buildClaimDetailPayload({
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ export async function syncKuaishouCloudRoleInfo(task: TaskRow) {
|
|||||||
source: 'claim_page_polling_bind_url_probe',
|
source: 'claim_page_polling_bind_url_probe',
|
||||||
actor: { source: 'system' },
|
actor: { source: 'system' },
|
||||||
})
|
})
|
||||||
task = probed.task
|
task = probed.task || task
|
||||||
|
|
||||||
const result = await refreshKuaishouCloudTaskRoleInfo(task, {
|
const result = await refreshKuaishouCloudTaskRoleInfo(task, {
|
||||||
source: 'claim_page_polling',
|
source: 'claim_page_polling',
|
||||||
actor: { source: 'system' },
|
actor: { source: 'system' },
|
||||||
recordEvent: false,
|
recordEvent: false,
|
||||||
})
|
})
|
||||||
return result.task
|
return result.task || task
|
||||||
} catch {
|
} catch {
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,13 +118,13 @@ export async function prepareKuaishouCloudFulfillmentTask(
|
|||||||
let readyTask = task;
|
let readyTask = task;
|
||||||
|
|
||||||
if (String(task.task_status || "").trim() !== "waiting_binding") {
|
if (String(task.task_status || "").trim() !== "waiting_binding") {
|
||||||
readyTask = await updateTask(task.id, {
|
readyTask = (await updateTask(task.id, {
|
||||||
task_status: "waiting_binding",
|
task_status: "waiting_binding",
|
||||||
claim_token: claimLinkState.token || task.claim_token || "",
|
claim_token: claimLinkState.token || task.claim_token || "",
|
||||||
claim_expires_at:
|
claim_expires_at:
|
||||||
claimLinkState.expiredAt || getTaskClaimExpiresAt(task),
|
claimLinkState.expiredAt || getTaskClaimExpiresAt(task),
|
||||||
updated_at: now,
|
updated_at: now,
|
||||||
});
|
})) || task;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -69,7 +69,15 @@ export function resolvePersistedCloudtentaclesContextWithFallback(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const token = String(session?.token || "").trim();
|
if (!session) {
|
||||||
|
lastError = createHttpError(
|
||||||
|
`cloudtentacles 账号 ${sourceKey} 没有可用 token`,
|
||||||
|
{ statusCode: 409, errorCode: "kuaishou_cloud_missing_cloud_token" }
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = String(session.token || "").trim();
|
||||||
if (!token) {
|
if (!token) {
|
||||||
lastError = createHttpError(
|
lastError = createHttpError(
|
||||||
`cloudtentacles 账号 ${sourceKey} 没有可用 token`,
|
`cloudtentacles 账号 ${sourceKey} 没有可用 token`,
|
||||||
|
|||||||
@@ -116,6 +116,12 @@ export async function dispatchKuaishouCloudFulfillmentTask(
|
|||||||
context_json: JSON.stringify(nextContext),
|
context_json: JSON.stringify(nextContext),
|
||||||
updated_at: now,
|
updated_at: now,
|
||||||
});
|
});
|
||||||
|
if (!updatedTask) {
|
||||||
|
throw createHttpError("快手 Cloud 发货状态更新失败", {
|
||||||
|
statusCode: 500,
|
||||||
|
errorCode: "kuaishou_cloud_dispatch_update_failed",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await createTaskEvent(
|
await createTaskEvent(
|
||||||
task.id,
|
task.id,
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ type TaskContext = {
|
|||||||
export async function syncDeliveryTasksForOrder(
|
export async function syncDeliveryTasksForOrder(
|
||||||
order: OrderRow,
|
order: OrderRow,
|
||||||
orderItems: OrderItemRow[],
|
orderItems: OrderItemRow[],
|
||||||
): Promise<Array<TaskRow | null>> {
|
): Promise<TaskRow[]> {
|
||||||
return syncDeliveryTasksForOrderWithDeps(order, orderItems)
|
return syncDeliveryTasksForOrderWithDeps(order, orderItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ export async function syncDeliveryTasksForOrderWithDeps(
|
|||||||
order: OrderRow,
|
order: OrderRow,
|
||||||
orderItems: OrderItemRow[],
|
orderItems: OrderItemRow[],
|
||||||
deps: DeliveryTaskDeps = {},
|
deps: DeliveryTaskDeps = {},
|
||||||
): Promise<Array<TaskRow | null>> {
|
): Promise<TaskRow[]> {
|
||||||
const {
|
const {
|
||||||
createTask: createDeliveryTask = createTask,
|
createTask: createDeliveryTask = createTask,
|
||||||
listTasksByOrderId: listTasks = listTasksByOrderId,
|
listTasksByOrderId: listTasks = listTasksByOrderId,
|
||||||
@@ -104,11 +104,12 @@ export async function syncDeliveryTasksForOrderWithDeps(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const itemMap = new Map(orderItems.map((item) => [item.id, item]))
|
const itemMap = new Map(orderItems.map((item) => [item.id, item]))
|
||||||
return Promise.all(existingTasks.map((task) => preparePaidTask({
|
const preparedTasks = await Promise.all(existingTasks.map((task) => preparePaidTask({
|
||||||
...task,
|
...task,
|
||||||
skuCode: itemMap.get(task.order_item_id)?.sku_code || '',
|
skuCode: itemMap.get(task.order_item_id)?.sku_code || '',
|
||||||
skuName: itemMap.get(task.order_item_id)?.sku_name || '',
|
skuName: itemMap.get(task.order_item_id)?.sku_name || '',
|
||||||
}, runtimeDeps)))
|
}, runtimeDeps)))
|
||||||
|
return preparedTasks.filter(isTaskRow)
|
||||||
}
|
}
|
||||||
|
|
||||||
const tasks: DeliveryTaskRow[] = []
|
const tasks: DeliveryTaskRow[] = []
|
||||||
@@ -243,11 +244,13 @@ export async function syncDeliveryTasksForOrderWithDeps(
|
|||||||
updatedAt: createdAt,
|
updatedAt: createdAt,
|
||||||
})
|
})
|
||||||
|
|
||||||
tasks.push({
|
if (task) {
|
||||||
...task,
|
tasks.push({
|
||||||
skuCode: item.sku_code,
|
...task,
|
||||||
skuName: item.sku_name,
|
skuCode: item.sku_code,
|
||||||
})
|
skuName: item.sku_name,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +258,8 @@ export async function syncDeliveryTasksForOrderWithDeps(
|
|||||||
return tasks
|
return tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(tasks.map((task) => preparePaidTask(task, runtimeDeps)))
|
const preparedTasks = await Promise.all(tasks.map((task) => preparePaidTask(task, runtimeDeps)))
|
||||||
|
return preparedTasks.filter(isTaskRow)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function preparePaidTask(
|
async function preparePaidTask(
|
||||||
@@ -380,6 +384,10 @@ function parseJsonObject(value: unknown): JsonObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isTaskRow(task: TaskRow | DeliveryTaskRow | null | undefined): task is TaskRow {
|
||||||
|
return Boolean(task && Number(task.id || 0) > 0)
|
||||||
|
}
|
||||||
|
|
||||||
function isKuaishouCloudExecutor(value: unknown): boolean {
|
function isKuaishouCloudExecutor(value: unknown): boolean {
|
||||||
return String(value || '').trim() === 'kuaishou_ct_assisted'
|
return String(value || '').trim() === 'kuaishou_ct_assisted'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,8 +181,10 @@ async function runFlowStep<T>(
|
|||||||
runner: () => Promise<T>,
|
runner: () => Promise<T>,
|
||||||
options: FlowStepOptions = {},
|
options: FlowStepOptions = {},
|
||||||
) {
|
) {
|
||||||
const retries = Number.isInteger(options.retries) && options.retries > 0 ? options.retries : 0
|
const rawRetries = Number(options.retries)
|
||||||
const retryDelayMs = Number.isFinite(options.retryDelayMs) && options.retryDelayMs > 0 ? options.retryDelayMs : 1000
|
const rawRetryDelayMs = Number(options.retryDelayMs)
|
||||||
|
const retries = Number.isInteger(rawRetries) && rawRetries > 0 ? rawRetries : 0
|
||||||
|
const retryDelayMs = Number.isFinite(rawRetryDelayMs) && rawRetryDelayMs > 0 ? rawRetryDelayMs : 1000
|
||||||
|
|
||||||
for (let attempt = 0; attempt <= retries; attempt += 1) {
|
for (let attempt = 0; attempt <= retries; attempt += 1) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ function normalizeKuaishouEticketSourceConfig(rawValue: unknown): KuaishouEticke
|
|||||||
baseUrl: String(source.baseUrl || DEFAULT_BASE_URL).trim() || DEFAULT_BASE_URL,
|
baseUrl: String(source.baseUrl || DEFAULT_BASE_URL).trim() || DEFAULT_BASE_URL,
|
||||||
shops: shops
|
shops: shops
|
||||||
.map((item) => normalizeKuaishouEticketShopConfig(item))
|
.map((item) => normalizeKuaishouEticketShopConfig(item))
|
||||||
.filter(Boolean),
|
.filter((item): item is KuaishouEticketShopConfig => Boolean(item)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ function loadScheduledJobsConfigFromFile() {
|
|||||||
export function normalizeScheduledJobsConfig(rawValue: unknown) {
|
export function normalizeScheduledJobsConfig(rawValue: unknown) {
|
||||||
const source = isPlainObject(rawValue) ? rawValue : {}
|
const source = isPlainObject(rawValue) ? rawValue : {}
|
||||||
const rawJobs = Array.isArray(source.jobs) ? source.jobs : []
|
const rawJobs = Array.isArray(source.jobs) ? source.jobs : []
|
||||||
const jobs = rawJobs.map((item) => normalizeScheduledJob(item)).filter(Boolean)
|
const jobs = rawJobs
|
||||||
|
.map((item) => normalizeScheduledJob(item))
|
||||||
|
.filter((item): item is ReturnType<typeof normalizeCloudtentaclesHealthJob> => Boolean(item))
|
||||||
const hasCloudtentaclesHealth = jobs.some((item) => item.id === CLOUDTENTACLES_HEALTH_JOB_ID)
|
const hasCloudtentaclesHealth = jobs.some((item) => item.id === CLOUDTENTACLES_HEALTH_JOB_ID)
|
||||||
|
|
||||||
if (!hasCloudtentaclesHealth) {
|
if (!hasCloudtentaclesHealth) {
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ export function buildErrorPayload(error: unknown, fallbackMessage: string) {
|
|||||||
export function sendRouteError(
|
export function sendRouteError(
|
||||||
res: Response,
|
res: Response,
|
||||||
error: unknown,
|
error: unknown,
|
||||||
fallbackMessage: string,
|
fallbackMessage = "服务内部错误",
|
||||||
scope: string
|
scope = "[route]"
|
||||||
): void {
|
): void {
|
||||||
const classification = classifyRouteError(error);
|
const classification = classifyRouteError(error);
|
||||||
const logger = classification.statusCode >= 500 ? logError : logWarn;
|
const logger = classification.statusCode >= 500 ? logError : logWarn;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"strict": false,
|
"strict": false,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"types": ["node"],
|
"types": ["node"],
|
||||||
"lib": ["ES2022"]
|
"lib": ["ES2022"]
|
||||||
|
|||||||
Reference in New Issue
Block a user