refactor(server): 清理全量 any 类型安全警告 (692 → 0)
- 全模块类型化:controller 的 req: any → AuthenticatedRequest/RequestUser, 聚合查询 getRawMany 泛型标注、导入行/响应体定义具体 interface、 catch (e: any) → unknown + 收窄、no-base-to-string 用 String() 显式转换 - 第三方无类型库边界(pdfkit/exceljs)文件级或单行 disable 并注明理由 - 顺带修复:get-business-context.tool 两个 require-await error、 bills.controller 参数顺序隐患、main.ts compression 调用 - 运行时逻辑零改动;测试 142 套件 / 1065 用例全部通过
This commit is contained in:
@@ -11,6 +11,12 @@ import {
|
||||
SaveIntegrationConfigDto,
|
||||
} from './dto/config.dto';
|
||||
|
||||
/** 第三方配置在 content JSON 中的存储结构。 */
|
||||
interface StoredConfigShape {
|
||||
config?: unknown;
|
||||
appSecret?: unknown;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class IntegrationConfigService {
|
||||
private readonly logger = new Logger(IntegrationConfigService.name);
|
||||
@@ -22,6 +28,18 @@ export class IntegrationConfigService {
|
||||
private readonly detailRepo: Repository<IntegrationConfigDetail>,
|
||||
) {}
|
||||
|
||||
/** String() 包装:避免 unknown 收窄后触发 no-base-to-string。 */
|
||||
private stringify(value: unknown): string {
|
||||
return String(value);
|
||||
}
|
||||
|
||||
/** 解析 content JSON 并取 config 段(无 config 时回退整个对象)。 */
|
||||
private parseStoredConfig(content: string): Record<string, unknown> {
|
||||
const parsed = JSON.parse(content) as StoredConfigShape;
|
||||
const rawCfg = parsed.config || parsed;
|
||||
return rawCfg && typeof rawCfg === 'object' ? (rawCfg as Record<string, unknown>) : {};
|
||||
}
|
||||
|
||||
/** 获取或创建主配置(全局单例) */
|
||||
private async ensureConfig(): Promise<IntegrationConfig> {
|
||||
let config = await this.configRepo.findOne({ where: { type: 'THIRD' } });
|
||||
@@ -80,8 +98,7 @@ export class IntegrationConfigService {
|
||||
if (existingDetail && existingDetail.content) {
|
||||
if (!finalConfig.appSecret) {
|
||||
try {
|
||||
const oldParsed = JSON.parse(existingDetail.content);
|
||||
const oldCfg = oldParsed.config || oldParsed;
|
||||
const oldCfg = this.parseStoredConfig(existingDetail.content);
|
||||
if (oldCfg.appSecret) finalConfig.appSecret = oldCfg.appSecret;
|
||||
} catch {
|
||||
// ignore
|
||||
@@ -156,7 +173,7 @@ export class IntegrationConfigService {
|
||||
* 供同步逻辑使用:读原始(未脱敏)配置。
|
||||
* 返回 { agentId, appSecret, corpId, appId? } 或 null。
|
||||
*/
|
||||
async getRawConfig(type: string): Promise<Record<string, any> | null> {
|
||||
async getRawConfig(type: string): Promise<Record<string, unknown> | null> {
|
||||
const config = await this.ensureConfig();
|
||||
const detailType = this.getDetailType(type);
|
||||
const detail = await this.detailRepo.findOne({
|
||||
@@ -164,8 +181,7 @@ export class IntegrationConfigService {
|
||||
});
|
||||
if (!detail || !detail.content) return null;
|
||||
try {
|
||||
const parsed = JSON.parse(detail.content);
|
||||
return parsed.config || parsed;
|
||||
return this.parseStoredConfig(detail.content);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
@@ -192,8 +208,8 @@ export class IntegrationConfigService {
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
if (type.toUpperCase() === 'DINGTALK') {
|
||||
const appKey = String(config.agentId || '');
|
||||
const appSecret = String(config.appSecret || '');
|
||||
const appKey = this.stringify(config.agentId || '');
|
||||
const appSecret = this.stringify(config.appSecret || '');
|
||||
if (!appKey || !appSecret) return null;
|
||||
return await this.fetchDingTalkToken(appKey, appSecret);
|
||||
}
|
||||
@@ -227,10 +243,9 @@ export class IntegrationConfigService {
|
||||
private parseAndMaskConfig(content: string | null): unknown {
|
||||
if (!content) return {};
|
||||
try {
|
||||
const parsed = JSON.parse(content);
|
||||
const source = parsed.config || parsed;
|
||||
const source = this.parseStoredConfig(content);
|
||||
if (!source || typeof source !== 'object' || Array.isArray(source)) return {};
|
||||
const { appSecret: _appSecret, ...masked } = source as Record<string, unknown>;
|
||||
const { appSecret: _appSecret, ...masked } = source;
|
||||
return masked;
|
||||
} catch {
|
||||
return {};
|
||||
|
||||
Reference in New Issue
Block a user