增强后端 TypeScript 严格类型检查

This commit is contained in:
yml2213
2026-05-26 10:07:19 +08:00
parent 6d9f267593
commit a2bce8b272
14 changed files with 66 additions and 31 deletions
+6 -1
View File
@@ -354,5 +354,10 @@ function setConfigValue(
current = current[key] as Record<string, unknown>;
}
current[configPath[configPath.length - 1]] = value;
const lastKey = configPath[configPath.length - 1];
if (!lastKey) {
return;
}
current[lastKey] = value;
}
+1 -1
View File
@@ -43,7 +43,7 @@ function resolveRequestId(req: Request): string {
}
function shouldSkipAccessLog(originalUrl: string, statusCode: number): boolean {
const pathname = String(originalUrl || "").split("?")[0];
const pathname = String(originalUrl || "").split("?")[0] || "";
return (
["/health", "/health/live", "/health/ready"].includes(pathname) &&
Number(statusCode) < 400
@@ -109,6 +109,10 @@ export function resolveOrderItemSyncPlan(
if (matchedIndex >= 0) {
const matched = unmatchedExisting.splice(matchedIndex, 1)[0]
if (!matched) {
creates.push(item)
continue
}
updates.push({
orderItemId: matched.id,
item,
+13 -12
View File
@@ -195,18 +195,19 @@ export async function updateTask(taskId: number | string, patch: TaskUpdatePatch
)
if (containsRuntimeContextPatch(patch)) {
await upsertTaskRuntimeContextWithClient(client, Number(taskId), {
runtimeSessionId: patch.runtime_session_id,
loginType: patch.login_type,
nickname: patch.nickname,
roleId: patch.role_id,
roleName: patch.role_name,
area: patch.area,
partitionName: patch.partition_name,
screenshotPath: patch.screenshot_path,
artifactsJson: patch.artifacts_json,
stateJson: patch.state_json,
}, patch.updated_at || current.updated_at)
const runtimeContextPatch: TaskRuntimeContextPatch = {}
if (patch.runtime_session_id !== undefined) runtimeContextPatch.runtimeSessionId = patch.runtime_session_id
if (patch.login_type !== undefined) runtimeContextPatch.loginType = patch.login_type
if (patch.nickname !== undefined) runtimeContextPatch.nickname = patch.nickname
if (patch.role_id !== undefined) runtimeContextPatch.roleId = patch.role_id
if (patch.role_name !== undefined) runtimeContextPatch.roleName = patch.role_name
if (patch.area !== undefined) runtimeContextPatch.area = patch.area
if (patch.partition_name !== undefined) runtimeContextPatch.partitionName = patch.partition_name
if (patch.screenshot_path !== undefined) runtimeContextPatch.screenshotPath = patch.screenshot_path
if (patch.artifacts_json !== undefined) runtimeContextPatch.artifactsJson = patch.artifacts_json
if (patch.state_json !== undefined) runtimeContextPatch.stateJson = patch.state_json
await upsertTaskRuntimeContextWithClient(client, Number(taskId), runtimeContextPatch, patch.updated_at || current.updated_at)
}
return getTaskByIdWithExecutor(client.query.bind(client) as TaskQueryExecutor, taskId)
+9 -1
View File
@@ -123,5 +123,13 @@ export function extractBearerToken(req: Request): string {
})
}
return matched[1]
const token = matched[1]?.trim()
if (!token) {
throw createHttpError('未登录或登录已失效', {
statusCode: 401,
errorCode: 'admin_auth_required',
})
}
return token
}
+10 -2
View File
@@ -16,6 +16,14 @@ const open91RateLimit = createRateLimitMiddleware({
},
})
function resolveErrorStatusCode(error: unknown): number {
if (!error || typeof error !== 'object' || !('statusCode' in error)) {
return 500
}
return Number(error.statusCode || 500)
}
router.post('/orders/create', open91RateLimit, async (req, res) => {
const requestId = createRequestId('91')
const startedAt = Date.now()
@@ -38,7 +46,7 @@ router.post('/orders/create', open91RateLimit, async (req, res) => {
res.status(200).json(result)
} catch (error) {
const message = error instanceof Error ? error.message : '系统错误'
const code = Number(error?.statusCode || 500) >= 500 ? 500 : 400
const code = resolveErrorStatusCode(error) >= 500 ? 500 : 400
logIntegration('[open-91/create]', '91卡券异步下单处理失败', {
requestId,
durationMs: Date.now() - startedAt,
@@ -70,7 +78,7 @@ router.post('/orders/query', open91RateLimit, async (req, res) => {
res.status(200).json(result)
} catch (error) {
const message = error instanceof Error ? error.message : '系统错误'
const code = Number(error?.statusCode || 500) >= 500 ? 500 : 400
const code = resolveErrorStatusCode(error) >= 500 ? 500 : 400
logIntegration('[open-91/query]', '91卡券订单查询处理失败', {
requestId,
durationMs: Date.now() - startedAt,
@@ -26,9 +26,9 @@ export async function notifyInternalSafely(payload: InternalNotificationPayload)
try {
const result = await sendInternalNotification({
title: payload.title,
body: payload.body,
category: payload.category,
url: payload.url,
...(payload.body !== undefined ? { body: payload.body } : {}),
...(payload.category !== undefined ? { category: payload.category } : {}),
...(payload.url !== undefined ? { url: payload.url } : {}),
})
markNotificationCooldown(cooldownKey)
return result
@@ -40,12 +40,12 @@ export async function sendInternalNotification(input: NotificationInput = {}) {
...(await Promise.all(barkRecipients.map(async (recipient: JsonObject) => {
try {
const result = await sendBarkNotification({
serverUrl: bark.serverUrl,
recipient,
title,
body,
group: `订单系统/${category}`,
url: input.url,
...(bark.serverUrl !== undefined ? { serverUrl: bark.serverUrl } : {}),
...(input.url !== undefined ? { url: input.url } : {}),
})
return mapNotificationResult('bark', recipient, recipient.deviceKey, true, '', result.status, result.response)
} catch (error) {
@@ -115,8 +115,8 @@ export async function upsertOrderFromSource(
provider: event.provider,
platform: event.platform,
shopId: event.shopId,
shopIdAliases: event.shopIdAliases,
item,
...(event.shopIdAliases !== undefined ? { shopIdAliases: event.shopIdAliases } : {}),
})),
)
const configuredItems = (resolvedItems as FulfillmentOrderItem[]).filter((item) => item.isConfigured)
@@ -155,7 +155,7 @@ export async function upsertOrderFromSource(
totalAmount: event.totalAmount,
currency: event.currency,
rawPayloadJson: JSON.stringify(event.rawPayload),
paidAt: event.paidAt,
...(event.paidAt !== undefined ? { paidAt: event.paidAt } : {}),
}
const mergedPayload = mergeSourceOrderState(existing, basePayload)
@@ -34,11 +34,12 @@ export async function cloudtentaclesRequest(pathname: unknown, options: JsonObje
})
try {
const body = normalizeRequestBody(options.body, headers['content-type'])
const response = await requestViaNodeHttp(url, {
method,
headers,
body: normalizeRequestBody(options.body, headers['content-type']),
signal: controller.signal,
...(body !== undefined ? { body } : {}),
})
const rawText = response.bodyText
@@ -42,15 +42,16 @@ export async function kuaishouEticketRequest(pathname: string, options: Kuaishou
userAgent: config.userAgent,
cookie: options.cookie ?? config.cookie,
contentType: options.contentType === null ? '' : options.contentType || inferContentType(options.body),
extra: options.headers,
...(options.headers !== undefined ? { extra: options.headers } : {}),
})
try {
const body = normalizeRequestBody(options.body, headers['content-type'])
const response = await requestViaNodeHttp(url, {
method,
headers,
body: normalizeRequestBody(options.body, headers['content-type']),
signal: controller.signal,
...(body !== undefined ? { body } : {}),
})
const rawText = response.bodyText
@@ -113,6 +113,13 @@ export async function upsertOpen91PendingOrder(payload: JsonObject = {}, config:
}
const [item] = event.items
if (!item) {
throw createHttpError('91卡券订单商品明细为空', {
statusCode: 400,
errorCode: 'open91_order_item_required',
})
}
const orderItems = await replaceOrderItems(order.id, [
{
skuCode: item.skuCode,
+1 -1
View File
@@ -62,7 +62,7 @@ export function buildHealthPayload(startupState: StartupState, shutdownStarted:
export function formatStartupError(error: unknown) {
if (error instanceof Error && error.message) {
return error.message.split("\n")[0].trim();
return error.message.split("\n")[0]?.trim() || "未知错误";
}
return String(error || "未知错误").trim();
+3 -3
View File
@@ -6,9 +6,9 @@
"allowJs": true,
"checkJs": true,
"noEmit": true,
"strict": false,
"noImplicitAny": true,
"strictNullChecks": true,
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"skipLibCheck": true,
"types": ["node"],
"lib": ["ES2022"]