Skip to content

Refactor: setup.ts duplicates allowlist logic from allowlist.ts #2

@AmberCXX

Description

@AmberCXX

问题

setup.ts 里存在一份与 allowlist.ts 完全相同的 allowlist 逻辑副本,两者之间没有任何 import 关系。


重复代码对照

setup.ts(第 24–57 行,独立副本)

interface AllowEntry {
  id: string;
  nickname: string;
}

interface Allowlist {
  allowed: AllowEntry[];
  auto_allow_next: boolean;
}

function migrateAllowlist(raw: any): Allowlist {
  if (!raw || !raw.allowed) return { allowed: [], auto_allow_next: false };
  const allowed: AllowEntry[] = raw.allowed.map((entry: any) => {
    if (typeof entry === "string") {
      return { id: entry, nickname: entry.split("@")[0] };
    }
    return entry as AllowEntry;
  });
  return { allowed, auto_allow_next: raw.auto_allow_next ?? false };
}

function loadAllowlist(): Allowlist { ... }   // 与 allowlist.ts 完全一致
function saveAllowlist(list: Allowlist): void { ... }  // 逻辑相同,仅多一行 mkdirSync

allowlist.ts(已导出,但 setup.ts 未 import)

export function migrateAllowlist(raw: any): Allowlist { ... }  // 完全相同
export function loadAllowlist(): Allowlist { ... }              // 完全相同
export function saveAllowlist(list: Allowlist): void { ... }   // 缺 mkdirSync

实际风险

allowlist 存储格式已经迁移过一次(旧 string[] → 新 AllowEntry[])。
如果未来再改格式,migrateAllowlist 需要同时在两处更新。
漏改任何一处,会导致 setup 阶段成功、运行时读取失败(或反过来),且错误现象是 allowlist 为空,而不是明显的报错,难以定位。


修复方案

第一步:allowlist.ts 的 saveAllowlist 加上目录创建

+import { DIR, ALLOW_FILE, log } from "./config.js";

 export function saveAllowlist(list: Allowlist): void {
+  fs.mkdirSync(DIR, { recursive: true });
   fs.writeFileSync(ALLOW_FILE, JSON.stringify(list, null, 2), { encoding: "utf-8", mode: 0o600 });
 }

mkdirSync({ recursive: true }) 是幂等操作,目录已存在时无副作用。

第二步:setup.ts 删除重复定义,改为 import

 import fs from "node:fs";
-import path from "node:path";
+import { DIR, CRED_FILE, ALLOW_FILE } from "./config.js";
+import { loadAllowlist, saveAllowlist } from "./allowlist.js";
+import type { AllowEntry } from "./types.js";

 const BASE_URL = "https://ilinkai.weixin.qq.com";
 const BOT_TYPE = "3";
-const DIR = path.join(process.env.HOME || "~", ".claude", "channels", "wechat");
-const CRED_FILE = path.join(DIR, "account.json");
-const ALLOW_FILE = path.join(DIR, "allowlist.json");

-interface AllowEntry { ... }
-interface Allowlist { ... }
-function migrateAllowlist(...) { ... }
-function loadAllowlist() { ... }
-function saveAllowlist(...) { ... }

影响范围

  • 零功能变更,纯重构
  • 删除约 30 行重复代码
  • 单一维护点,防止日后格式迁移时两处逻辑分叉

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions