增强后端 TypeScript 严格类型检查
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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"]
|
||||
|
||||
Reference in New Issue
Block a user