统一前后端代码格式化配置

This commit is contained in:
yml2213
2026-08-16 17:27:12 +08:00
parent 8705f6a6a1
commit 5c7c3e14e3
278 changed files with 6386 additions and 5500 deletions
@@ -17,7 +17,9 @@ type BarkSendInput = {
}
export async function sendBarkNotification(input: BarkSendInput) {
const serverUrl = String(input.serverUrl || 'https://api.day.app').trim().replace(/\/+$/, '')
const serverUrl = String(input.serverUrl || 'https://api.day.app')
.trim()
.replace(/\/+$/, '')
const deviceKey = String(input.recipient?.deviceKey || '').trim()
const title = String(input.title || '').trim()
const body = String(input.body || '').trim()
@@ -88,11 +90,7 @@ export async function sendBarkNotification(input: BarkSendInput) {
}
function buildBarkEndpoint(serverUrl: string, deviceKey: string, title: string, body: string) {
const segments = [
serverUrl,
encodeURIComponent(deviceKey),
encodeURIComponent(title),
]
const segments = [serverUrl, encodeURIComponent(deviceKey), encodeURIComponent(title)]
if (body) {
segments.push(encodeURIComponent(body))
@@ -124,7 +122,10 @@ function isBarkFailure(parsed: unknown) {
function resolveBarkErrorMessage(parsed: unknown, responseText: string, status: number) {
if (isPlainObject(parsed)) {
return String(parsed.message || parsed.msg || parsed.error || '').trim() || `Bark 通知发送失败,HTTP ${status}`
return (
String(parsed.message || parsed.msg || parsed.error || '').trim() ||
`Bark 通知发送失败,HTTP ${status}`
)
}
return String(responseText || '').trim() || `Bark 通知发送失败,HTTP ${status}`
@@ -1,10 +1,7 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import {
createDefaultNotificationConfig,
normalizeNotificationConfig,
} from './config-service.js'
import { createDefaultNotificationConfig, normalizeNotificationConfig } from './config-service.js'
test('normalizeNotificationConfig normalizes bark and wpush recipients', () => {
assert.deepEqual(
@@ -3,10 +3,7 @@ import type { JsonObject } from '../../types/json.js'
import { APP_CONFIG_KEYS } from '../../config/app-config-keys.js'
import { PROJECT_ROOT } from '../../config/runtime.js'
import {
readAppConfigEntry,
saveAppConfigEntry,
} from '../config/app-config-store.js'
import { readAppConfigEntry, saveAppConfigEntry } from '../config/app-config-store.js'
const NOTIFICATION_CONFIG_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'notification-config.json')
const DEFAULT_BARK_SERVER_URL = 'https://api.day.app'
@@ -46,8 +43,9 @@ export function listEnabledBarkRecipients(config: JsonObject = getNotificationCo
return []
}
return (Array.isArray(config.channels?.bark?.recipients) ? config.channels.bark.recipients : [])
.filter((item: JsonObject) => item.enabled !== false && String(item.deviceKey || '').trim())
return (
Array.isArray(config.channels?.bark?.recipients) ? config.channels.bark.recipients : []
).filter((item: JsonObject) => item.enabled !== false && String(item.deviceKey || '').trim())
}
export function listEnabledWpushRecipients(config: JsonObject = getNotificationConfig()) {
@@ -55,8 +53,11 @@ export function listEnabledWpushRecipients(config: JsonObject = getNotificationC
return []
}
return (Array.isArray(config.channels?.wpush?.recipients) ? config.channels.wpush.recipients : [])
.filter((item: JsonObject) => item.enabled !== false && String(item.apiKey || item.apikey || '').trim())
return (
Array.isArray(config.channels?.wpush?.recipients) ? config.channels.wpush.recipients : []
).filter(
(item: JsonObject) => item.enabled !== false && String(item.apiKey || item.apikey || '').trim(),
)
}
export function normalizeNotificationConfig(rawValue: unknown) {
@@ -107,11 +107,9 @@ export function notifyKuaishouCloudAssetNotEnough({
`商品:${String(skuName || binding.skuName || flowRecord.internalSkuName || '').trim() || '-'}`,
].join('\n'),
category: 'kuaishou_cloud_asset_not_enough',
cooldownKey: [
'kuaishou_cloud_asset_not_enough',
taskRecord.id || '',
binding.skuId || '',
].join(':'),
cooldownKey: ['kuaishou_cloud_asset_not_enough', taskRecord.id || '', binding.skuId || ''].join(
':',
),
})
}
@@ -135,9 +133,16 @@ export function notifyCloudtentaclesAuthExpired({
`接口:${String(pathname || '').trim() || '-'}`,
`错误码:${String(errorCode || '').trim() || '-'}`,
`原因:${String(message || '').trim() || '登录态已失效,请到后台重新登录'}`,
].filter(Boolean).join('\n'),
]
.filter(Boolean)
.join('\n'),
category: 'cloudtentacles_auth_expired',
cooldownKey: ['cloudtentacles_auth_expired', normalizedSourceKey || 'default', pathname, errorCode].join(':'),
cooldownKey: [
'cloudtentacles_auth_expired',
normalizedSourceKey || 'default',
pathname,
errorCode,
].join(':'),
cooldownMs: Number(cooldownSeconds || 600) * 1000,
})
}
@@ -161,9 +166,13 @@ export function notifyCloudtentaclesAssetLow({
`当前余额:${Number(asset || 0)}`,
`提醒阈值:${Number(threshold || 0)}`,
'请及时补充 cloudtentacles 余额,避免自动履约失败。',
].filter(Boolean).join('\n'),
]
.filter(Boolean)
.join('\n'),
category: 'cloudtentacles_asset_low',
cooldownKey: ['cloudtentacles_asset_low', normalizedSourceKey || 'default', threshold].join(':'),
cooldownKey: ['cloudtentacles_asset_low', normalizedSourceKey || 'default', threshold].join(
':',
),
cooldownMs: Number(cooldownSeconds || 1800) * 1000,
})
}
@@ -186,7 +195,11 @@ export function notifyOpen91PendingConfig({
`原因:${String(reason || '').trim() || '未命中履约配置'}`,
].join('\n'),
category: 'open91_pending_config',
cooldownKey: ['open91_pending_config', orderNo || orderRecord.platform_order_id || '', productNo].join(':'),
cooldownKey: [
'open91_pending_config',
orderNo || orderRecord.platform_order_id || '',
productNo,
].join(':'),
})
}
@@ -258,9 +271,7 @@ function formatTaskLine(task: unknown) {
}
function toRecord(value: unknown): JsonObject {
return value && typeof value === 'object' && !Array.isArray(value)
? value as JsonObject
: {}
return value && typeof value === 'object' && !Array.isArray(value) ? (value as JsonObject) : {}
}
function isNotificationCoolingDown(cooldownKey: unknown, cooldownMs = DEFAULT_COOLDOWN_MS) {
@@ -37,59 +37,79 @@ export async function sendInternalNotification(input: NotificationInput = {}) {
}
const results = [
...(await Promise.all(barkRecipients.map(async (recipient: JsonObject) => {
try {
const result = await sendBarkNotification({
recipient,
title,
body,
group: `订单系统/${category}`,
...(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) {
logWarn('[notification/bark]', 'Bark 内部通知发送失败', {
recipientId: recipient.id,
recipientName: recipient.name,
error,
})
return mapNotificationResult(
'bark',
recipient,
recipient.deviceKey,
false,
error instanceof Error ? error.message : 'Bark 内部通知发送失败',
isPlainObject(error) ? Number(error.statusCode || 0) || 0 : 0,
isPlainObject(error) ? error.context || null : null,
)
}
}))),
...(await Promise.all(wpushRecipients.map(async (recipient: JsonObject) => {
try {
const result = await sendWpushNotification({
recipient,
title,
body,
})
return mapNotificationResult('wpush', recipient, recipient.apiKey, true, '', result.status, result.response)
} catch (error) {
logWarn('[notification/wpush]', 'WPush 内部通知发送失败', {
recipientId: recipient.id,
recipientName: recipient.name,
error,
})
return mapNotificationResult(
'wpush',
recipient,
recipient.apiKey,
false,
error instanceof Error ? error.message : 'WPush 内部通知发送失败',
isPlainObject(error) ? Number(error.statusCode || 0) || 0 : 0,
isPlainObject(error) ? error.context || null : null,
)
}
}))),
...(await Promise.all(
barkRecipients.map(async (recipient: JsonObject) => {
try {
const result = await sendBarkNotification({
recipient,
title,
body,
group: `订单系统/${category}`,
...(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) {
logWarn('[notification/bark]', 'Bark 内部通知发送失败', {
recipientId: recipient.id,
recipientName: recipient.name,
error,
})
return mapNotificationResult(
'bark',
recipient,
recipient.deviceKey,
false,
error instanceof Error ? error.message : 'Bark 内部通知发送失败',
isPlainObject(error) ? Number(error.statusCode || 0) || 0 : 0,
isPlainObject(error) ? error.context || null : null,
)
}
}),
)),
...(await Promise.all(
wpushRecipients.map(async (recipient: JsonObject) => {
try {
const result = await sendWpushNotification({
recipient,
title,
body,
})
return mapNotificationResult(
'wpush',
recipient,
recipient.apiKey,
true,
'',
result.status,
result.response,
)
} catch (error) {
logWarn('[notification/wpush]', 'WPush 内部通知发送失败', {
recipientId: recipient.id,
recipientName: recipient.name,
error,
})
return mapNotificationResult(
'wpush',
recipient,
recipient.apiKey,
false,
error instanceof Error ? error.message : 'WPush 内部通知发送失败',
isPlainObject(error) ? Number(error.statusCode || 0) || 0 : 0,
isPlainObject(error) ? error.context || null : null,
)
}
}),
)),
]
return {
@@ -66,11 +66,12 @@ test('sendWpushNotification sends POST json payload', async () => {
test('sendWpushNotification rejects missing api key', async () => {
await assert.rejects(
() => sendWpushNotification({
recipient: {},
title: '测试标题',
body: '测试内容',
}),
() =>
sendWpushNotification({
recipient: {},
title: '测试标题',
body: '测试内容',
}),
(error: any) => {
assert.equal(error?.errorCode, 'wpush_api_key_required')
return true
@@ -97,7 +97,12 @@ export async function sendWpushNotification(input: WpushSendInput) {
async function requestViaNodeHttp(
url: URL,
{ method, headers, body, signal }: {
{
method,
headers,
body,
signal,
}: {
method: string
headers: Record<string, string>
body?: string
@@ -107,25 +112,29 @@ async function requestViaNodeHttp(
const transport = url.protocol === 'https:' ? https : http
return new Promise((resolve, reject) => {
const request = transport.request(url, {
method,
headers,
rejectUnauthorized: false,
}, (response) => {
const chunks: Buffer[] = []
const request = transport.request(
url,
{
method,
headers,
rejectUnauthorized: false,
},
(response) => {
const chunks: Buffer[] = []
response.on('data', (chunk) => {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))
})
response.on('end', () => {
resolve({
ok: Number(response.statusCode || 0) >= 200 && Number(response.statusCode || 0) < 300,
status: Number(response.statusCode || 0),
bodyText: Buffer.concat(chunks).toString('utf8'),
response.on('data', (chunk) => {
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))
})
})
})
response.on('end', () => {
resolve({
ok: Number(response.statusCode || 0) >= 200 && Number(response.statusCode || 0) < 300,
status: Number(response.statusCode || 0),
bodyText: Buffer.concat(chunks).toString('utf8'),
})
})
},
)
request.on('error', reject)
@@ -135,11 +144,15 @@ async function requestViaNodeHttp(
error.name = 'AbortError'
request.destroy(error)
} else {
signal.addEventListener('abort', () => {
const error = new Error('Request aborted')
error.name = 'AbortError'
request.destroy(error)
}, { once: true })
signal.addEventListener(
'abort',
() => {
const error = new Error('Request aborted')
error.name = 'AbortError'
request.destroy(error)
},
{ once: true },
)
}
}
@@ -179,7 +192,10 @@ function isWpushFailure(parsed: unknown) {
function resolveWpushErrorMessage(parsed: unknown, responseText: string, status: number) {
if (isPlainObject(parsed)) {
return String(parsed.message || parsed.msg || parsed.error || '').trim() || `WPush 通知发送失败,HTTP ${status}`
return (
String(parsed.message || parsed.msg || parsed.error || '').trim() ||
`WPush 通知发送失败,HTTP ${status}`
)
}
return String(responseText || '').trim() || `WPush 通知发送失败,HTTP ${status}`