跳转到内容

共享包开发

shared/ 放跨子项目复用的代码。目前有三个包,全部源码直出:main 与 exports 直接指向 src/index.ts, 没有构建步骤,子项目用 workspace:* 引用。改动即时生效,但也意味着没有编译期保护(见第五节)。

包 用途 引用方
@cikio/types 跨项目共享的领域类型(当前是消息中心的类型) ccu/、message/、forum/
@cikio/utils 通用工具函数 ccu/、message/
@cikio/moderation 内容审核判定与留痕(纯逻辑库 + 词库脚本 + 迁移) authserver/、ccu/、forum/
shared/
├─ package.json # name: cikio-shared,私有包;只提供 typecheck
├─ tsconfig.json # 工作区统一编译口径
└─ packages/
├─ types/ { package.json, tsconfig.json, src/index.ts, src/message.ts }
├─ utils/ { package.json, tsconfig.json, src/index.ts }
└─ moderation/
├─ package.json tsconfig.json README.md wrangler.toml
├─ src/ # 源码 + *.test.mjs
├─ scripts/ # 词库抓取 / 导入 / 发布脚本
└─ migrations/ # D1 表结构(共享库 cikio-moderation)

shared/tsconfig.json 的口径是 target: ES2022、module: ESNext、moduleResolution: Bundler、 strict: true、allowImportingTsExtensions、isolatedModules、verbatimModuleSyntax。 新包直接沿用这份配置,不要各写一套。

pnpm-workspace.yaml 里 shared/packages/* 是通配,所以在 packages/ 下新建目录会自动成为工作区成员, 不需要改根配置。

{
"name": "@cikio/xxx",
"version": "0.0.0",
"private": true,
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": { ".": "./src/index.ts" },
"files": ["src"],
"scripts": { "typecheck": "tsc --noEmit" }
}

要点:

  • private: true + version: 0.0.0:不发 npm,只做工作区内部引用。
  • 三个入口字段(main / types / exports)都指向 src/index.ts,这是「源码直出」的全部机制。
  • 需要子项目直接引子路径时,在 exports 里显式加一条,别让引用方写深层相对路径。

子项目里这样引用:

import type { Message, MessageId } from '@cikio/types';
import { formatDate } from '@cikio/utils';

依赖必须写 "@cikio/xxx": "workspace:*"。改完依赖记得 pnpm install 并提交根 pnpm-lock.yaml。

三、@cikio/moderation:一个完整例子

Section titled “三、@cikio/moderation:一个完整例子”

它是唯一带运行时逻辑、测试与数据库迁移的共享包,可以作为后续共享包的样板。

  • 职责:给定文本,返回审核判定(放行 / 送审 / 替换 / 拦截)与命中明细;判定结果另行落库留痕。

  • 源码模块:types / normalize(归一化,处理同形字与干扰字符)/ matcher(引擎)/ policy(动作策略)/ snapshot(词库快照读写)/ moderator(对外主入口)/ records(明细落库)/ word-input(词库录入校验)。

  • 零运行时依赖:只用平台 API(KV / D1 由调用方注入),便于被 Worker 直接打包。

  • 测试:node --test "src/**/*.test.mjs"(Node 内置 runner,不引测试框架):

    终端窗口
    pnpm --filter @cikio/moderation test
  • 数据:表结构在 shared/packages/moderation/migrations/,作用于共享库 cikio-moderation; 词库快照走 KV(binding MODERATION_WORDS)。包内 wrangler.toml 不是部署单元, 只用于跑迁移与脚本。

  • 词库脚本:scripts/ 下区分抓取(fetch-lexicon.mjs)、导入(import-lexicon.mjs)、 发布快照(publish-wordlist.mjs),共用 lib.mjs。

  • 降级口径:调用方在词库读不到时按「放行 + 标记 degraded + 记日志」处理,不静默失败,也不误拦用户。

接入方(authserver、ccu、forum)通过各自的 D1 与 KV binding 传入数据库与词库,不要在业务站里另建一份敏感词表。

终端窗口
pnpm --filter shared typecheck # 或 pnpm typecheck(会带上所有子项目)
pnpm --filter @cikio/moderation test # 有测试的包
pnpm build # 确认引用方仍能构建

共享包的改动会影响所有引用方,提交前至少跑一次全量 pnpm typecheck 与 pnpm build。

  • 没有编译期保护:包是 .ts 源码直出,没有独立的构建/类型产物,改坏了引用方也不会在 pnpm install 时报警, 只在类型检查或运行时暴露。改导出签名时务必自己跑一遍引用方的 typecheck。
  • 不要往里塞业务:只放真正被两个以上子项目用的东西。单站专用逻辑留在该站内部, 否则共享包会变成谁都改不动的大杂烩。

相关:共享包用法、Monorepo 总览、开发问题与踩坑记录。