151 行
4.8 KiB
JavaScript
151 行
4.8 KiB
JavaScript
require('dotenv/config');
|
|
|
|
const { getConfig } = require('../config');
|
|
const { resolveEmailDeliveryStatus } = require('../services/email');
|
|
|
|
function assertCondition(condition, message) {
|
|
if (!condition) {
|
|
throw new Error(message);
|
|
}
|
|
}
|
|
|
|
function formatList(items) {
|
|
return items.filter(Boolean).join(', ');
|
|
}
|
|
|
|
function evaluateWecom(config) {
|
|
if (!config.wecomEnabled) {
|
|
return { state: 'disabled', detail: '企业微信入口未启用', checks: [] };
|
|
}
|
|
|
|
const missing = [];
|
|
if (!String(config.wecomCorpId ?? '').trim()) missing.push('WECOM_CORP_ID');
|
|
if (!String(config.wecomAgentId ?? '').trim()) missing.push('WECOM_AGENT_ID');
|
|
if (!String(config.wecomAgentSecret ?? '').trim()) missing.push('WECOM_AGENT_SECRET');
|
|
if (config.wecomOauthEnabled && !String(config.wecomRedirectUri ?? '').trim()) missing.push('WECOM_REDIRECT_URI');
|
|
if (config.wecomEntryEnabled && !String(config.wecomAllowedReturnHosts ?? '').trim()) missing.push('WECOM_ALLOWED_RETURN_HOSTS');
|
|
|
|
assertCondition(missing.length === 0, `企业微信配置不完整:${formatList(missing)}`);
|
|
|
|
if (!config.wecomEntryEnabled || !config.wecomOauthEnabled) {
|
|
return {
|
|
state: 'degraded',
|
|
detail: `企业微信基础配置已启用,但入口=${config.wecomEntryEnabled ? 'on' : 'off'} oauth=${config.wecomOauthEnabled ? 'on' : 'off'}`,
|
|
checks: ['corpId=present', 'agentId=present'],
|
|
};
|
|
}
|
|
|
|
return {
|
|
state: 'ready',
|
|
detail: '企业微信入口与免登配置齐全',
|
|
checks: [
|
|
'corpId=present',
|
|
'agentId=present',
|
|
'redirectUri=present',
|
|
`pcWebLogin=${config.wecomPcWebLoginEnabled ? 'on' : 'off'}`,
|
|
],
|
|
};
|
|
}
|
|
|
|
function evaluateEmail(config) {
|
|
const status = resolveEmailDeliveryStatus(config);
|
|
if (status.reasons.includes('email_disabled')) {
|
|
return { state: 'disabled', detail: '企业邮箱 SMTP 未启用', checks: [] };
|
|
}
|
|
|
|
const reasonLabels = {
|
|
email_from_missing: 'EMAIL_FROM',
|
|
smtp_host_missing: 'SMTP_HOST',
|
|
smtp_port_invalid: 'SMTP_PORT',
|
|
smtp_auth_incomplete: 'SMTP_USER/SMTP_PASS',
|
|
};
|
|
const missing = status.reasons.map((reason) => reasonLabels[reason] ?? reason);
|
|
|
|
assertCondition(status.ready, `SMTP 配置不完整:${formatList(missing)}`);
|
|
|
|
return {
|
|
state: 'ready',
|
|
detail: 'SMTP 基础配置齐全(仅做配置契约校验,不发真实邮件)',
|
|
checks: ['from=present', 'host=present', 'port=valid', `secure=${config.smtpSecure}`],
|
|
};
|
|
}
|
|
|
|
function evaluateOcr(config) {
|
|
const provider = String(config.ocrProvider ?? 'off').trim();
|
|
if (!provider || provider === 'off') {
|
|
return { state: 'disabled', detail: 'OCR provider 已关闭', checks: [] };
|
|
}
|
|
|
|
if (provider === 'mock') {
|
|
return { state: 'mock', detail: 'OCR 使用 mock provider', checks: [`provider=${provider}`] };
|
|
}
|
|
|
|
if (provider === 'tencent') {
|
|
const missing = [];
|
|
if (!String(config.tencentSecretId ?? '').trim()) missing.push('TENCENT_SECRET_ID');
|
|
if (!String(config.tencentSecretKey ?? '').trim()) missing.push('TENCENT_SECRET_KEY');
|
|
assertCondition(missing.length === 0, `腾讯 OCR 配置不完整:${formatList(missing)}`);
|
|
return {
|
|
state: 'ready',
|
|
detail: '腾讯 OCR 配置齐全',
|
|
checks: [`provider=${provider}`, 'credentials=present', 'region=present'],
|
|
};
|
|
}
|
|
|
|
return {
|
|
state: 'custom',
|
|
detail: `OCR provider=${provider},请确认对应适配器契约`,
|
|
checks: [`provider=${provider}`],
|
|
};
|
|
}
|
|
|
|
function evaluateBridge(config) {
|
|
if (!config.imNotifierEnabled) {
|
|
return { state: 'disabled', detail: '消息回流桥接未启用', checks: [] };
|
|
}
|
|
|
|
const missing = [];
|
|
if (!String(config.appOrigin ?? '').trim()) missing.push('APP_ORIGIN');
|
|
if (!String(config.fieldEncryptionKey ?? '').trim()) missing.push('FIELD_ENCRYPTION_KEY');
|
|
assertCondition(missing.length === 0, `消息桥接配置不完整:${formatList(missing)}`);
|
|
|
|
return {
|
|
state: 'ready',
|
|
detail: '消息回流桥接配置齐全',
|
|
checks: ['appOrigin=present'],
|
|
};
|
|
}
|
|
|
|
function printSection(name, section) {
|
|
const tag = section.state === 'ready' || section.state === 'mock' || section.state === 'disabled' || section.state === 'custom'
|
|
? 'PASS'
|
|
: section.state === 'degraded'
|
|
? 'WARN'
|
|
: 'INFO';
|
|
console.log(`[${tag}] ${name}: ${section.detail}`);
|
|
for (const line of section.checks ?? []) {
|
|
console.log(` - ${line}`);
|
|
}
|
|
}
|
|
|
|
function main() {
|
|
const config = getConfig();
|
|
console.log('[R30] 开始 external deps smoke');
|
|
|
|
const sections = {
|
|
wecom: evaluateWecom(config),
|
|
email: evaluateEmail(config),
|
|
ocr: evaluateOcr(config),
|
|
bridge: evaluateBridge(config),
|
|
};
|
|
|
|
printSection('企业微信', sections.wecom);
|
|
printSection('SMTP 邮件', sections.email);
|
|
printSection('OCR', sections.ocr);
|
|
printSection('消息桥接', sections.bridge);
|
|
|
|
console.log('[R30][PASS] external deps smoke 通过');
|
|
}
|
|
|
|
main();
|