@h-ai/reach 0.1.0-alpha5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../messages/en-US.json","../messages/zh-CN.json","../src/reach-i18n.ts","../src/reach-config.ts","../src/reach-types.ts","../src/providers/reach-provider-aliyun-sms.ts","../src/providers/reach-provider-api.ts","../src/providers/reach-provider-console.ts","../src/providers/reach-provider-smtp.ts","../src/reach-send.ts","../src/reach-template.ts","../src/repositories/reach-repository-send-log.ts","../src/repositories/reach-repository-template.ts","../src/reach-main.ts"],"names":["core","logger","toReachError","err","ok","require","templateRegistry","dndConfig","providers","TABLE_NAME","BaseReldbCrudRepository"],"mappings":"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","file":"index.js","sourcesContent":["{\n \"$schema\": \"https://inlang.com/schema/inlang-message-format\",\n \"reach_notInitialized\": \"Reach module not initialized, call reach.init() first\",\n \"reach_initFailed\": \"Reach module initialization failed: {error}\",\n \"reach_unsupportedType\": \"Unsupported reach type: {type}\",\n \"reach_sendFailed\": \"Send failed: {error}\",\n \"reach_templateNotFound\": \"Template not found: {template}\",\n \"reach_templateRenderFailed\": \"Template render failed: {error}\",\n \"reach_invalidRecipient\": \"Invalid recipient: {recipient}\",\n \"reach_providerNotFound\": \"Provider not found: {provider}\",\n \"reach_providerRequired\": \"No provider specified, set provider field in message or template\",\n \"reach_dndBlocked\": \"Message discarded by Do Not Disturb period\",\n \"reach_dndDeferred\": \"Message deferred by Do Not Disturb period, will be sent after DND ends\",\n \"reach_smsSendFailed\": \"SMS send failed: {error}\",\n \"reach_emailSendFailed\": \"Email send failed: {error}\",\n \"reach_apiSendFailed\": \"API callback send failed: {error}\",\n \"reach_configError\": \"Reach config validation failed: {error}\",\n \"reach_config_nameRequired\": \"Provider name is required\",\n \"reach_config_hostRequired\": \"SMTP host is required\",\n \"reach_config_fromRequired\": \"Sender address (from) is required\",\n \"reach_config_accessKeyIdRequired\": \"AccessKey ID is required\",\n \"reach_config_accessKeySecretRequired\": \"AccessKey Secret is required\",\n \"reach_config_signNameRequired\": \"SMS sign name is required\",\n \"reach_config_urlRequired\": \"Callback URL is required\",\n \"reach_config_dndTimeInvalid\": \"Invalid time format, must be HH:mm (24-hour)\",\n \"reach_config_templateNameRequired\": \"Template name is required\",\n \"reach_config_templateProviderRequired\": \"Template provider is required\",\n \"reach_config_templateBodyRequired\": \"Template body is required\",\n \"reach_config_providersRequired\": \"At least one provider is required\",\n \"reach_templateDbInitFailed\": \"Template database initialization failed: {error}\",\n \"reach_templateSaveFailed\": \"Template save failed: {error}\",\n \"reach_templateDeleteFailed\": \"Template delete failed: {error}\"\n}\n","{\n \"$schema\": \"https://inlang.com/schema/inlang-message-format\",\n \"reach_notInitialized\": \"触达模块尚未初始化,请先调用 reach.init()\",\n \"reach_initFailed\": \"触达模块初始化失败: {error}\",\n \"reach_unsupportedType\": \"不支持的触达类型: {type}\",\n \"reach_sendFailed\": \"发送失败: {error}\",\n \"reach_templateNotFound\": \"模板未找到: {template}\",\n \"reach_templateRenderFailed\": \"模板渲染失败: {error}\",\n \"reach_invalidRecipient\": \"无效的接收方: {recipient}\",\n \"reach_providerNotFound\": \"Provider 未找到: {provider}\",\n \"reach_providerRequired\": \"未指定 Provider,请在消息或模板中设置 provider 字段\",\n \"reach_dndBlocked\": \"当前处于免打扰时段,消息已丢弃\",\n \"reach_dndDeferred\": \"当前处于免打扰时段,消息已暂存待发送\",\n \"reach_smsSendFailed\": \"短信发送失败: {error}\",\n \"reach_emailSendFailed\": \"邮件发送失败: {error}\",\n \"reach_apiSendFailed\": \"API 回调发送失败: {error}\",\n \"reach_configError\": \"触达配置校验失败:{error}\",\n \"reach_config_nameRequired\": \"Provider 名称不能为空\",\n \"reach_config_hostRequired\": \"SMTP 服务器地址不能为空\",\n \"reach_config_fromRequired\": \"发件人地址不能为空\",\n \"reach_config_accessKeyIdRequired\": \"AccessKey ID 不能为空\",\n \"reach_config_accessKeySecretRequired\": \"AccessKey Secret 不能为空\",\n \"reach_config_signNameRequired\": \"短信签名不能为空\",\n \"reach_config_urlRequired\": \"回调 URL 不能为空\",\n \"reach_config_dndTimeInvalid\": \"时间格式无效,须为 HH:mm(24 小时制)\",\n \"reach_config_templateNameRequired\": \"模板名称不能为空\",\n \"reach_config_templateProviderRequired\": \"模板绑定的 Provider 不能为空\",\n \"reach_config_templateBodyRequired\": \"模板正文不能为空\",\n \"reach_config_providersRequired\": \"至少需要配置一个 Provider\",\n \"reach_templateDbInitFailed\": \"模板数据库初始化失败: {error}\",\n \"reach_templateSaveFailed\": \"模板保存失败: {error}\",\n \"reach_templateDeleteFailed\": \"模板删除失败: {error}\"\n}\n","/**\n * @h-ai/reach — i18n\n *\n * 本文件提供触达模块的 i18n 文案访问入口。\n * @module reach-i18n\n */\n\nimport { core } from '@h-ai/core'\nimport messagesEnUS from '../messages/en-US.json'\nimport messagesZhCN from '../messages/zh-CN.json'\n\n// ─── i18n ───\n\n/**\n * 触达模块文案 Key 类型\n */\ntype ReachMessageKey = keyof typeof messagesZhCN\n\n/**\n * 获取触达模块文案。\n * @param key - 文案 Key\n * @param options - 插值参数与格式化选项\n * @returns 本地化后的文案字符串\n */\nexport const reachM = core.i18n.createMessageGetter<ReachMessageKey>({\n 'zh-CN': messagesZhCN,\n 'en-US': messagesEnUS,\n})\n","/**\n * @h-ai/reach — 配置 Schema\n *\n * 本文件定义触达模块的错误码、Zod Schema 和配置类型。\n * @module reach-config\n */\n\nimport { z } from 'zod'\n\nimport { reachM } from './reach-i18n.js'\n\n// ─── 单个 Provider 配置 Schema ───\n\n/**\n * Console Provider 配置(开发/测试用,将消息输出到日志)\n */\nexport const ConsoleProviderConfigSchema = z.object({\n /** Provider 唯一名称 */\n name: z.string().min(1, reachM('reach_config_nameRequired')),\n type: z.literal('console'),\n})\n\n/**\n * SMTP 邮件 Provider 配置\n *\n * @example\n * ```ts\n * {\n * name: 'email',\n * type: 'smtp',\n * host: 'smtp.example.com',\n * port: 465,\n * secure: true,\n * user: 'noreply@example.com',\n * pass: 'password',\n * from: 'noreply@example.com'\n * }\n * ```\n */\nexport const SmtpProviderConfigSchema = z.object({\n /** Provider 唯一名称 */\n name: z.string().min(1, reachM('reach_config_nameRequired')),\n type: z.literal('smtp'),\n /** SMTP 服务器地址 */\n host: z.string().min(1, reachM('reach_config_hostRequired')),\n /** SMTP 端口(默认 465) */\n port: z.number().int().min(1).max(65535).default(465),\n /** 是否使用 TLS(默认 true) */\n secure: z.boolean().default(true),\n /** SMTP 认证用户名 */\n user: z.string().optional(),\n /** SMTP 认证密码 */\n pass: z.string().optional(),\n /** 发件人地址 */\n from: z.string().min(1, reachM('reach_config_fromRequired')),\n})\n\n/**\n * 阿里云短信 Provider 配置(通过 HTTP API 调用,无需 SDK)\n *\n * @example\n * ```ts\n * {\n * name: 'sms',\n * type: 'aliyun-sms',\n * accessKeyId: 'LTAI...',\n * accessKeySecret: '...',\n * signName: '某某科技',\n * endpoint: 'dysmsapi.aliyuncs.com'\n * }\n * ```\n */\nexport const AliyunSmsProviderConfigSchema = z.object({\n /** Provider 唯一名称 */\n name: z.string().min(1, reachM('reach_config_nameRequired')),\n type: z.literal('aliyun-sms'),\n /** 阿里云 AccessKey ID */\n accessKeyId: z.string().min(1, reachM('reach_config_accessKeyIdRequired')),\n /** 阿里云 AccessKey Secret */\n accessKeySecret: z.string().min(1, reachM('reach_config_accessKeySecretRequired')),\n /** 短信签名 */\n signName: z.string().min(1, reachM('reach_config_signNameRequired')),\n /** API 端点(默认 dysmsapi.aliyuncs.com) */\n endpoint: z.string().default('dysmsapi.aliyuncs.com'),\n})\n\n/**\n * API 回调 Provider 配置(通用 HTTP 回调)\n *\n * @example\n * ```ts\n * {\n * name: 'webhook',\n * type: 'api',\n * url: 'https://api.example.com/notify',\n * method: 'POST',\n * headers: { 'Authorization': 'Bearer xxx' }\n * }\n * ```\n */\nexport const ApiProviderConfigSchema = z.object({\n /** Provider 唯一名称 */\n name: z.string().min(1, reachM('reach_config_nameRequired')),\n type: z.literal('api'),\n /** 回调 URL */\n url: z.string().min(1, reachM('reach_config_urlRequired')),\n /** HTTP 方法(默认 POST) */\n method: z.enum(['POST', 'PUT']).default('POST'),\n /** 自定义请求头 */\n headers: z.record(z.string(), z.string()).optional(),\n /** 请求超时毫秒数(默认 10000) */\n timeout: z.number().int().min(0).default(10000),\n})\n\n/**\n * 单个 Provider 配置 Schema(判别联合体)\n */\nexport const ProviderConfigSchema = z.discriminatedUnion('type', [\n ConsoleProviderConfigSchema,\n SmtpProviderConfigSchema,\n AliyunSmsProviderConfigSchema,\n ApiProviderConfigSchema,\n])\n\n/** 单个 Provider 配置类型(parse 后) */\nexport type ProviderConfig = z.infer<typeof ProviderConfigSchema>\n\n/** Console 配置类型 */\nexport type ConsoleProviderConfig = z.infer<typeof ConsoleProviderConfigSchema>\n\n/** SMTP 配置类型 */\nexport type SmtpProviderConfig = z.infer<typeof SmtpProviderConfigSchema>\n\n/** 阿里云短信配置类型 */\nexport type AliyunSmsProviderConfig = z.infer<typeof AliyunSmsProviderConfigSchema>\n\n/** API 回调配置类型 */\nexport type ApiProviderConfig = z.infer<typeof ApiProviderConfigSchema>\n\n// ─── DND(免打扰)配置 Schema ───\n\n/**\n * 免打扰时间段配置\n *\n * 在指定的时间段内,根据策略处理消息:\n * - `discard`:直接丢弃,返回 DND_BLOCKED 错误\n * - `delay`:暂存到数据库(状态为 pending),DND 结束后由定时任务集中发送\n *\n * 时间使用 HH:mm 格式(24 小时制),支持跨午夜(如 22:00-08:00)。\n *\n * @example\n * ```ts\n * {\n * enabled: true,\n * strategy: 'delay',\n * start: '22:00',\n * end: '08:00'\n * }\n * ```\n */\nexport const DndConfigSchema = z.object({\n /** 是否启用免打扰(默认 false) */\n enabled: z.boolean().default(false),\n /** 免打扰策略:discard 丢弃 / delay 延时发送(默认 discard) */\n strategy: z.enum(['discard', 'delay']).default('discard'),\n /** 免打扰开始时间(HH:mm 格式) */\n start: z.string().regex(/^([01]\\d|2[0-3]):[0-5]\\d$/, reachM('reach_config_dndTimeInvalid')).default('00:00'),\n /** 免打扰结束时间(HH:mm 格式) */\n end: z.string().regex(/^([01]\\d|2[0-3]):[0-5]\\d$/, reachM('reach_config_dndTimeInvalid')).default('00:00'),\n})\n\n/** DND 配置类型 */\nexport type DndConfig = z.infer<typeof DndConfigSchema>\n\n// ─── 模板配置 Schema ───\n\n/**\n * 模板配置 Schema(通过配置文件定义模板)\n *\n * @example\n * ```yaml\n * templates:\n * - name: verification_code\n * provider: email\n * subject: \"验证码: {code}\"\n * body: \"您的验证码是 {code},有效期 {minutes} 分钟。\"\n * ```\n */\nexport const TemplateConfigSchema = z.object({\n /** 模板名称 */\n name: z.string().min(1, reachM('reach_config_templateNameRequired')),\n /** 绑定的 Provider 名称 */\n provider: z.string().min(1, reachM('reach_config_templateProviderRequired')),\n /** 邮件主题模板 */\n subject: z.string().optional(),\n /** 正文模板 */\n body: z.string().min(1, reachM('reach_config_templateBodyRequired')),\n})\n\n/** 模板配置类型 */\nexport type TemplateConfig = z.infer<typeof TemplateConfigSchema>\n\n// ─── 模块配置 Schema ───\n\n/**\n * 触达模块配置 Schema\n *\n * 接受一个 Provider 配置数组,支持同时注册多个 Provider。\n * 支持通过配置文件定义模板和免打扰时间段。\n */\nexport const ReachConfigSchema = z.object({\n /** Provider 配置列表 */\n providers: z.array(ProviderConfigSchema).min(1, reachM('reach_config_providersRequired')),\n /** 模板配置(通过配置文件注册) */\n templates: z.array(TemplateConfigSchema).optional(),\n /** 免打扰配置 */\n dnd: DndConfigSchema.optional(),\n})\n\n/** 触达模块配置类型(parse 后) */\nexport type ReachConfig = z.infer<typeof ReachConfigSchema>\n\n/**\n * 触达模块配置输入类型\n */\nexport type ReachConfigInput = z.input<typeof ReachConfigSchema>\n","/**\n * @h-ai/reach — 类型定义\n *\n * 本文件定义触达模块的核心接口和类型。\n * @module reach-types\n */\n\nimport type { ErrorInfo, HaiResult } from '@h-ai/core'\nimport type { ProviderConfig, ReachConfig, ReachConfigInput } from './reach-config.js'\nimport { core } from '@h-ai/core'\n\n// ─── 错误定义(照 @h-ai/core 范式) ───\n\nconst ReachErrorInfo = {\n SEND_FAILED: '001:500',\n TEMPLATE_NOT_FOUND: '002:404',\n TEMPLATE_RENDER_FAILED: '003:500',\n INVALID_RECIPIENT: '004:400',\n PROVIDER_NOT_FOUND: '005:500',\n DND_BLOCKED: '006:403',\n DND_DEFERRED: '007:202',\n NOT_INITIALIZED: '010:500',\n UNSUPPORTED_TYPE: '011:400',\n CONFIG_ERROR: '012:500',\n} as const satisfies ErrorInfo\n\nexport const HaiReachError = core.error.buildHaiErrorsDef('reach', ReachErrorInfo)\n\n// ─── 渠道类型 ───\n\n/**\n * 触达渠道类型\n *\n * - `email` — 邮件\n * - `sms` — 短信\n * - `api` — API 回调\n */\nexport type ReachChannel = 'email' | 'sms' | 'api'\n\n// ─── 消息与模板 ───\n\n/**\n * 触达消息(发送请求)\n *\n * 通过 `provider` 字段指定目标 Provider,通过 `template` 字段指定模板。\n *\n * @example\n * ```ts\n * // 使用模板发送邮件\n * const msg: ReachMessage = {\n * provider: 'email',\n * to: 'user@example.com',\n * template: 'welcome',\n * vars: { userName: '张三' },\n * }\n *\n * // 使用模板发送短信\n * const msg: ReachMessage = {\n * provider: 'sms',\n * to: '13800138000',\n * template: 'verification_code',\n * vars: { code: '123456' },\n * }\n * ```\n */\nexport interface ReachMessage {\n /** 目标 Provider 名称(对应 Provider 配置中的 name) */\n provider: string\n /** 接收方(邮箱地址或手机号) */\n to: string\n /** 邮件主题(直接发送时使用) */\n subject?: string\n /** 消息正文(直接发送时使用) */\n body?: string\n /** 模板名称(使用模板发送时指定) */\n template?: string\n /** 模板变量(使用模板发送时传入) */\n vars?: Record<string, string>\n /** Provider 扩展参数(如短信 Provider 的模板编码、签名等) */\n extra?: Record<string, unknown>\n}\n\n/**\n * 发送结果\n */\nexport interface SendResult {\n /** 是否发送成功 */\n success: boolean\n /** Provider 返回的消息 ID(如有) */\n messageId?: string\n /** 是否被延时(DND delay 策略暂存,待 DND 结束后发送) */\n deferred?: boolean\n}\n\n/**\n * 触达模板定义\n *\n * 每个模板绑定到一个 Provider,发送时按模板中的 `provider` 路由。\n *\n * @example\n * ```ts\n * const template: ReachTemplate = {\n * name: 'verification_code',\n * provider: 'email',\n * subject: '验证码: {code}',\n * body: '您的验证码是 {code},有效期 {minutes} 分钟。',\n * }\n * ```\n */\nexport interface ReachTemplate {\n /** 模板名称(唯一标识) */\n name: string\n /** 绑定的 Provider 名称 */\n provider: string\n /** 邮件主题模板(支持 `{var}` 占位符,仅 email) */\n subject?: string\n /** 消息正文模板(支持 `{var}` 占位符) */\n body: string\n}\n\n/**\n * 渲染后的模板\n */\nexport interface RenderedTemplate {\n /** 渲染后的主题 */\n subject?: string\n /** 渲染后的正文 */\n body: string\n}\n\n// ─── 操作接口 ───\n\n/**\n * 发送操作接口\n */\nexport interface SendOperations {\n /**\n * 发送触达消息\n *\n * @param message - 触达消息\n * @returns 发送结果\n *\n * @example\n * ```ts\n * const result = await reach.send({\n * provider: 'email',\n * to: 'user@example.com',\n * template: 'welcome',\n * vars: { userName: '张三' },\n * })\n * ```\n */\n send: (message: ReachMessage) => Promise<HaiResult<SendResult>>\n}\n\n// ─── 模板注册表接口 ───\n\n/**\n * 模板注册表接口\n *\n * 所有模板通过数据库持久化存储,避免节点间状态不一致。\n * 配置文件中的模板在 init 时写入数据库。\n */\nexport interface ReachTemplateRegistry {\n /** 按名称解析模板 */\n resolve: (name: string) => Promise<HaiResult<ReachTemplate>>\n /** 保存模板到数据库(upsert) */\n save: (template: ReachTemplate) => Promise<HaiResult<void>>\n /** 批量保存模板到数据库 */\n saveBatch: (templates: ReachTemplate[]) => Promise<HaiResult<void>>\n /** 从数据库删除模板 */\n remove: (name: string) => Promise<HaiResult<void>>\n /** 列出所有模板 */\n list: () => Promise<HaiResult<ReachTemplate[]>>\n /** 渲染模板(从数据库解析后渲染) */\n render: (name: string, vars: Record<string, string>) => Promise<HaiResult<RenderedTemplate>>\n}\n\n// ─── 函数接口 ───\n\n/**\n * 触达模块函数接口\n *\n * @example\n * ```ts\n * import { reach } from '@h-ai/reach'\n *\n * // 初始化(同时注册多个 Provider)\n * await reach.init({\n * providers: [\n * { name: 'email', type: 'smtp', host: 'smtp.example.com', from: 'no-reply@example.com' },\n * { name: 'sms', type: 'aliyun-sms', accessKeyId: '...', accessKeySecret: '...', signName: '...' },\n * ],\n * })\n *\n * // 保存模板(绑定到 Provider)\n * await reach.template.save({\n * name: 'welcome',\n * provider: 'email',\n * subject: '欢迎 {userName}',\n * body: '亲爱的 {userName},欢迎使用我们的服务!',\n * })\n *\n * // 发送(指定 Provider)\n * await reach.send({ provider: 'email', to: 'user@example.com', template: 'welcome', vars: { userName: '张三' } })\n *\n * // 关闭\n * await reach.close()\n * ```\n */\nexport interface ReachFunctions extends SendOperations {\n /** 初始化触达模块(注册多个 Provider) */\n init: (config: ReachConfigInput) => Promise<HaiResult<void>>\n /** 当前配置(未初始化时为 null) */\n readonly config: ReachConfig | null\n /** 是否已初始化 */\n readonly isInitialized: boolean\n /** 模板注册表 */\n readonly template: ReachTemplateRegistry\n /** 关闭连接并释放资源 */\n close: () => Promise<void>\n}\n\n// ─── Provider 接口 ───\n\n/**\n * 触达 Provider 接口\n *\n * 由具体实现(console / smtp / aliyun-sms / api)提供。\n */\nexport interface ReachProvider {\n /** Provider 名称 */\n readonly name: string\n /** 连接/初始化 Provider */\n connect: (config: ProviderConfig) => Promise<HaiResult<void>>\n /** 发送消息 */\n send: (message: ReachMessage) => Promise<HaiResult<SendResult>>\n /** 关闭连接 */\n close: () => Promise<void>\n /** 是否已连接 */\n isConnected: () => boolean\n}\n","/**\n * @h-ai/reach — 阿里云短信 Provider\n *\n * 通过阿里云 SMS HTTP API 发送短信的 Provider 实现(无需 SDK)。\n * @module reach-provider-aliyun-sms\n */\n\nimport type { HaiError, HaiResult } from '@h-ai/core'\nimport type { AliyunSmsProviderConfig, ProviderConfig } from '../reach-config.js'\n\nimport type { ReachMessage, ReachProvider, SendResult } from '../reach-types.js'\nimport { createHmac, randomUUID } from 'node:crypto'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { reachM } from '../reach-i18n.js'\nimport { HaiReachError } from '../reach-types.js'\n\nconst logger = core.logger.child({ module: 'reach', scope: 'provider-aliyun-sms' })\n\n/**\n * 将异常包装为 ReachError\n */\nfunction toReachError(error: unknown): HaiError {\n return {\n code: HaiReachError.SEND_FAILED.code,\n message: reachM('reach_smsSendFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n cause: error,\n }\n}\n\n/**\n * 对字符串做 RFC 3986 编码\n */\nfunction percentEncode(str: string): string {\n return encodeURIComponent(str)\n .replace(/\\+/g, '%20')\n .replace(/\\*/g, '%2A')\n .replace(/~/g, '%7E')\n}\n\n/**\n * 构造阿里云 POP API 签名\n *\n * @param params - 请求参数(不含 Signature)\n * @param accessKeySecret - AccessKey Secret\n * @param method - HTTP 方法\n * @returns 签名值\n */\nfunction signRequest(params: Record<string, string>, accessKeySecret: string, method: string): string {\n const sortedKeys = Object.keys(params).sort()\n const canonicalQuery = sortedKeys\n .map(k => `${percentEncode(k)}=${percentEncode(params[k])}`)\n .join('&')\n\n const stringToSign = `${method}&${percentEncode('/')}&${percentEncode(canonicalQuery)}`\n // 阿里云 POP API 规范要求使用 HMAC-SHA1 签名\n const hmac = createHmac('sha1', `${accessKeySecret}&`)\n hmac.update(stringToSign)\n return hmac.digest('base64')\n}\n\n/**\n * 创建阿里云短信 Provider(直接调用 HTTP API)\n *\n * @returns 阿里云短信 Provider 实例\n */\nexport function createAliyunSmsProvider(): ReachProvider {\n let smsConfig: AliyunSmsProviderConfig | null = null\n\n return {\n name: 'aliyun-sms',\n\n async connect(config: ProviderConfig): Promise<HaiResult<void>> {\n if (config.type !== 'aliyun-sms') {\n return err(\n HaiReachError.CONFIG_ERROR,\n reachM('reach_unsupportedType', { params: { type: config.type } }),\n )\n }\n\n smsConfig = config\n logger.info('Aliyun SMS provider connected', { endpoint: config.endpoint })\n return ok(undefined)\n },\n\n async close(): Promise<void> {\n smsConfig = null\n logger.info('Aliyun SMS provider disconnected')\n },\n\n isConnected(): boolean {\n return smsConfig !== null\n },\n\n async send(message: ReachMessage): Promise<HaiResult<SendResult>> {\n if (!smsConfig) {\n return err(\n HaiReachError.NOT_INITIALIZED,\n reachM('reach_notInitialized'),\n )\n }\n\n const templateCode = message.extra?.templateCode as string | undefined\n logger.debug('Sending SMS', { to: message.to, templateCode })\n\n try {\n const params: Record<string, string> = {\n AccessKeyId: smsConfig.accessKeyId,\n Action: 'SendSms',\n Format: 'JSON',\n PhoneNumbers: message.to,\n SignName: smsConfig.signName,\n SignatureMethod: 'HMAC-SHA1',\n SignatureNonce: randomUUID(),\n SignatureVersion: '1.0',\n TemplateCode: templateCode ?? '',\n Timestamp: new Date().toISOString().replace(/\\.\\d{3}Z$/, 'Z'),\n Version: '2017-05-25',\n }\n\n if (message.vars) {\n params.TemplateParam = JSON.stringify(message.vars)\n }\n\n params.Signature = signRequest(params, smsConfig.accessKeySecret, 'GET')\n\n const queryString = Object.entries(params)\n .map(([k, v]) => `${percentEncode(k)}=${percentEncode(v)}`)\n .join('&')\n\n const url = `https://${smsConfig.endpoint}/?${queryString}`\n const response = await fetch(url)\n const body = await response.json() as { Code: string, Message: string, BizId?: string }\n\n if (body.Code !== 'OK') {\n logger.warn('SMS send returned non-OK status', { code: body.Code, message: body.Message })\n return err(\n HaiReachError.SEND_FAILED,\n reachM('reach_smsSendFailed', { params: { error: body.Message } }),\n )\n }\n\n logger.info('SMS sent', { to: message.to, bizId: body.BizId })\n return ok({ success: true, messageId: body.BizId })\n }\n catch (error) {\n logger.error('SMS send failed', { to: message.to, error })\n return err(toReachError(error))\n }\n },\n }\n}\n","/**\n * @h-ai/reach — API 回调 Provider\n *\n * 通用 HTTP API 回调 Provider,通过 HTTP 请求发送触达消息。\n * @module reach-provider-api\n */\n\nimport type { HaiError, HaiResult } from '@h-ai/core'\nimport type { ApiProviderConfig, ProviderConfig } from '../reach-config.js'\n\nimport type { ReachMessage, ReachProvider, SendResult } from '../reach-types.js'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { reachM } from '../reach-i18n.js'\nimport { HaiReachError } from '../reach-types.js'\n\nconst logger = core.logger.child({ module: 'reach', scope: 'provider-api' })\n\n/**\n * 将异常包装为 ReachError\n */\nfunction toReachError(error: unknown): HaiError {\n return {\n code: HaiReachError.SEND_FAILED.code,\n message: reachM('reach_apiSendFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n cause: error,\n }\n}\n\n/**\n * 创建 API 回调 Provider\n *\n * @returns API 回调 Provider 实例\n */\nexport function createApiProvider(): ReachProvider {\n let apiConfig: ApiProviderConfig | null = null\n\n return {\n name: 'api',\n\n async connect(config: ProviderConfig): Promise<HaiResult<void>> {\n if (config.type !== 'api') {\n return err(\n HaiReachError.CONFIG_ERROR,\n reachM('reach_unsupportedType', { params: { type: config.type } }),\n )\n }\n\n apiConfig = config\n logger.info('API provider connected', { url: config.url, method: config.method })\n return ok(undefined)\n },\n\n async close(): Promise<void> {\n apiConfig = null\n logger.info('API provider disconnected')\n },\n\n isConnected(): boolean {\n return apiConfig !== null\n },\n\n async send(message: ReachMessage): Promise<HaiResult<SendResult>> {\n if (!apiConfig) {\n return err(\n HaiReachError.NOT_INITIALIZED,\n reachM('reach_notInitialized'),\n )\n }\n\n logger.debug('Sending via API callback', { url: apiConfig.url, to: message.to })\n\n try {\n const payload = {\n to: message.to,\n subject: message.subject,\n body: message.body,\n template: message.template,\n vars: message.vars,\n extra: message.extra,\n }\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), apiConfig.timeout)\n\n try {\n const response = await fetch(apiConfig.url, {\n method: apiConfig.method,\n headers: {\n 'Content-Type': 'application/json',\n ...apiConfig.headers,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const text = await response.text()\n logger.warn('API callback returned non-OK status', { status: response.status, body: text })\n return err(\n HaiReachError.SEND_FAILED,\n reachM('reach_apiSendFailed', { params: { error: `HTTP ${response.status}: ${text}` } }),\n )\n }\n\n const result = await response.json() as { messageId?: string }\n logger.info('API callback sent', { to: message.to, messageId: result.messageId })\n return ok({ success: true, messageId: result.messageId })\n }\n finally {\n clearTimeout(timeoutId)\n }\n }\n catch (error) {\n logger.error('API callback send failed', { to: message.to, error })\n return err(toReachError(error))\n }\n },\n }\n}\n","/**\n * @h-ai/reach — Console Provider\n *\n * 开发/测试用 Provider,将触达消息输出到日志。\n * @module reach-provider-console\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ProviderConfig } from '../reach-config.js'\n\nimport type { ReachMessage, ReachProvider, SendResult } from '../reach-types.js'\nimport { core, ok } from '@h-ai/core'\n\nconst logger = core.logger.child({ module: 'reach', scope: 'provider-console' })\n\n/**\n * 创建 Console Provider\n *\n * @returns Console Provider 实例\n */\nexport function createConsoleProvider(): ReachProvider {\n let connected = false\n\n return {\n name: 'console',\n\n async connect(_config: ProviderConfig): Promise<HaiResult<void>> {\n connected = true\n logger.info('Console provider connected')\n return ok(undefined)\n },\n\n async close(): Promise<void> {\n connected = false\n logger.info('Console provider disconnected')\n },\n\n isConnected(): boolean {\n return connected\n },\n\n async send(message: ReachMessage): Promise<HaiResult<SendResult>> {\n logger.debug('Sending message via console', {\n provider: message.provider,\n to: message.to,\n subject: message.subject,\n body: message.body,\n template: message.template,\n vars: message.vars,\n extra: message.extra,\n })\n\n const messageId = `console-${Date.now()}`\n return ok({ success: true, messageId })\n },\n }\n}\n","/**\n * @h-ai/reach — SMTP Email Provider\n *\n * 使用 nodemailer 发送邮件的 Provider 实现。\n * @module reach-provider-smtp\n */\n\nimport type { HaiError, HaiResult } from '@h-ai/core'\nimport type { ProviderConfig, SmtpProviderConfig } from '../reach-config.js'\n\nimport type { ReachMessage, ReachProvider, SendResult } from '../reach-types.js'\nimport { createRequire } from 'node:module'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { reachM } from '../reach-i18n.js'\nimport { HaiReachError } from '../reach-types.js'\n\nconst logger = core.logger.child({ module: 'reach', scope: 'provider-smtp' })\n\n/**\n * 将异常包装为 ReachError\n */\nfunction toReachError(error: unknown): HaiError {\n return {\n code: HaiReachError.SEND_FAILED.code,\n message: reachM('reach_emailSendFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n cause: error,\n }\n}\n\n/**\n * 创建 SMTP Provider\n *\n * @returns SMTP Provider 实例\n */\nexport function createSmtpProvider(): ReachProvider {\n let transporter: unknown = null\n let smtpConfig: SmtpProviderConfig | null = null\n\n return {\n name: 'smtp',\n\n async connect(config: ProviderConfig): Promise<HaiResult<void>> {\n if (config.type !== 'smtp') {\n return err(\n HaiReachError.CONFIG_ERROR,\n reachM('reach_unsupportedType', { params: { type: config.type } }),\n )\n }\n\n try {\n const require = createRequire(import.meta.url)\n const nodemailer = require('nodemailer')\n\n smtpConfig = config\n transporter = nodemailer.createTransport({\n host: config.host,\n port: config.port,\n secure: config.secure,\n auth: config.user\n ? { user: config.user, pass: config.pass }\n : undefined,\n })\n\n logger.info('SMTP provider connected', { host: config.host, port: config.port })\n return ok(undefined)\n }\n catch (error) {\n logger.error('SMTP connection failed', { error })\n return err(toReachError(error))\n }\n },\n\n async close(): Promise<void> {\n if (transporter && typeof (transporter as Record<string, unknown>).close === 'function') {\n (transporter as { close: () => void }).close()\n }\n transporter = null\n smtpConfig = null\n logger.info('SMTP provider disconnected')\n },\n\n isConnected(): boolean {\n return transporter !== null\n },\n\n async send(message: ReachMessage): Promise<HaiResult<SendResult>> {\n if (!transporter || !smtpConfig) {\n return err(\n HaiReachError.NOT_INITIALIZED,\n reachM('reach_notInitialized'),\n )\n }\n\n logger.debug('Sending email', { to: message.to, subject: message.subject })\n\n try {\n const sendMail = (transporter as { sendMail: (opts: unknown) => Promise<{ messageId: string }> }).sendMail.bind(transporter)\n const info = await sendMail({\n from: smtpConfig.from,\n to: message.to,\n subject: message.subject ?? '',\n html: message.body ?? '',\n })\n\n logger.info('Email sent', { to: message.to, messageId: info.messageId })\n return ok({ success: true, messageId: info.messageId })\n }\n catch (error) {\n logger.error('Email send failed', { to: message.to, error })\n return err(toReachError(error))\n }\n },\n }\n}\n","/**\n * @h-ai/reach — 发送逻辑\n *\n * 本文件封装触达模块的发送逻辑,包括: - 消息预处理(模板渲染 + Provider 路由推导) - DND(免打扰)时间段检查与策略处理(discard / delay) - 通过 SendLogRepository 持久化发送记录 - DND 恢复定时任务(flush pending 消息)\n * @module reach-send\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { DndConfig } from './reach-config.js'\nimport type { ReachMessage, ReachProvider, ReachTemplateRegistry, SendResult } from './reach-types.js'\n\nimport type { SendLogRepository } from './repositories/reach-repository-send-log.js'\nimport { cache } from '@h-ai/cache'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { reachM } from './reach-i18n.js'\nimport {\n HaiReachError,\n\n} from './reach-types.js'\n\nconst logger = core.logger.child({ module: 'reach', scope: 'send' })\n\n/** 稳定的节点标识,用于分布式锁 owner(进程级别唯一) */\nconst reachNodeId = `reach:${crypto.randomUUID()}`\n\n// ─── DND(免打扰)检查 ───\n\n/**\n * 解析 HH:mm 时间为当天的分钟数(0~1439)\n *\n * @param time - HH:mm 格式的时间字符串\n * @returns 分钟数\n */\nfunction parseTimeToMinutes(time: string): number {\n const [h, m] = time.split(':').map(Number)\n return h * 60 + m\n}\n\n/**\n * 检查当前时间是否处于免打扰时段\n *\n * 支持跨午夜时段(如 22:00 → 08:00)。\n *\n * @param dnd - DND 配置\n * @param now - 当前时间(默认 new Date())\n * @returns 是否被 DND 拦截\n */\nexport function isDndBlocked(dnd: DndConfig | undefined, now: Date = new Date()): boolean {\n if (!dnd?.enabled) {\n return false\n }\n\n const startMin = parseTimeToMinutes(dnd.start)\n const endMin = parseTimeToMinutes(dnd.end)\n const currentMin = now.getHours() * 60 + now.getMinutes()\n\n if (startMin === endMin) {\n return false\n }\n\n if (startMin < endMin) {\n return currentMin >= startMin && currentMin < endMin\n }\n\n return currentMin >= startMin || currentMin < endMin\n}\n\n/**\n * 计算距离 DND 结束还有多少毫秒\n *\n * @param dnd - DND 配置\n * @param now - 当前时间\n * @returns 毫秒数\n */\nexport function msUntilDndEnd(dnd: DndConfig, now: Date = new Date()): number {\n const endMin = parseTimeToMinutes(dnd.end)\n const currentMin = now.getHours() * 60 + now.getMinutes()\n const currentSec = now.getSeconds()\n\n let diffMin = endMin - currentMin\n if (diffMin <= 0) {\n diffMin += 24 * 60\n }\n return diffMin * 60 * 1000 - currentSec * 1000\n}\n\n// ─── 消息预处理 ───\n\n/**\n * 预处理消息:如果指定了模板,渲染模板并填充 subject/body,\n * 同时从模板中推导 Provider 名称。\n */\nexport async function preprocessMessage(\n message: ReachMessage,\n templateRegistry: ReachTemplateRegistry,\n): Promise<HaiResult<ReachMessage>> {\n if (!message.template) {\n return ok(message)\n }\n\n const rendered = await templateRegistry.render(message.template, message.vars ?? {})\n if (!rendered.success) {\n return rendered\n }\n\n const template = await templateRegistry.resolve(message.template)\n\n const processed: ReachMessage = {\n ...message,\n provider: message.provider || (template.success ? template.data.provider : '') || '',\n subject: message.subject ?? rendered.data.subject,\n body: message.body ?? rendered.data.body,\n }\n return ok(processed)\n}\n\n// ─── 发送记录持久化(通过 Repository) ───\n\n/**\n * 保存发送记录到数据库\n */\nasync function saveSendRecord(\n repo: SendLogRepository | null,\n message: ReachMessage,\n status: 'sent' | 'pending',\n provider: string,\n messageId?: string,\n): Promise<void> {\n if (!repo) {\n return\n }\n try {\n await repo.create({\n provider,\n toAddr: message.to,\n subject: message.subject ?? null,\n body: message.body ?? null,\n template: message.template ?? null,\n varsJson: message.vars ? JSON.stringify(message.vars) : null,\n extraJson: message.extra ? JSON.stringify(message.extra) : null,\n status,\n messageId: messageId ?? null,\n createdAt: Date.now(),\n })\n }\n catch {\n logger.debug('Send record not saved (db module unavailable)')\n }\n}\n\n// ─── DND 恢复定时任务 ───\n\n/** 定时器引用 */\nlet dndTimer: ReturnType<typeof setTimeout> | null = null\n\n/** 保存调度器参数,用于循环调度 */\nlet schedulerContext: { dndConfig: DndConfig, providers: Map<string, ReachProvider>, repo: SendLogRepository | null } | null = null\n\n/**\n * 启动 DND 恢复定时器\n *\n * 在 DND 结束时自动获取所有 pending 状态记录并逐条发送,\n * 并在 flush 完成后重新调度下一个 DND 周期。\n */\nexport function startDndScheduler(\n dndConfig: DndConfig,\n providers: Map<string, ReachProvider>,\n repo: SendLogRepository | null,\n): void {\n stopDndScheduler()\n\n if (!dndConfig.enabled || dndConfig.strategy !== 'delay') {\n return\n }\n\n schedulerContext = { dndConfig, providers, repo }\n\n // 如果当前不在 DND 时段,不需要启动定时器\n if (!isDndBlocked(dndConfig)) {\n // 但仍然尝试 flush 一次(可能上次 DND 结束后有残留 pending)\n flushPendingMessages(providers, repo).catch((error) => {\n logger.warn('Failed to flush pending messages on init', { error })\n })\n scheduleDndCheck()\n return\n }\n\n scheduleFlushAtDndEnd()\n}\n\n/**\n * 在 DND 结束时触发 flush 并重新调度\n */\nfunction scheduleFlushAtDndEnd(): void {\n if (!schedulerContext)\n return\n const { dndConfig, providers, repo } = schedulerContext\n\n const delayMs = msUntilDndEnd(dndConfig)\n logger.info('DND scheduler started', { delayMs, dndEnd: dndConfig.end })\n\n dndTimer = setTimeout(() => {\n logger.info('DND period ended, flushing pending messages')\n flushPendingMessages(providers, repo)\n .catch((error) => {\n logger.error('Failed to flush pending messages', { error })\n })\n .finally(() => {\n // 重新调度:等待下一个 DND 周期\n scheduleDndCheck()\n })\n }, delayMs)\n}\n\n/**\n * 定期检查是否进入 DND 时段,进入后切换到 flush 调度\n */\nfunction scheduleDndCheck(): void {\n if (!schedulerContext)\n return\n const { dndConfig } = schedulerContext\n\n // 每分钟检查一次是否进入 DND\n const CHECK_INTERVAL = 60 * 1000\n dndTimer = setTimeout(() => {\n if (!schedulerContext)\n return\n if (isDndBlocked(dndConfig)) {\n scheduleFlushAtDndEnd()\n }\n else {\n scheduleDndCheck()\n }\n }, CHECK_INTERVAL)\n}\n\n/**\n * 停止 DND 恢复定时器\n */\nexport function stopDndScheduler(): void {\n if (dndTimer !== null) {\n clearTimeout(dndTimer)\n dndTimer = null\n }\n}\n\n/**\n * 重置内部状态(close 时调用)\n */\nexport function resetSendState(): void {\n stopDndScheduler()\n schedulerContext = null\n}\n\n/**\n * 从数据库获取所有 pending 记录并逐条发送\n *\n * 多节点部署时通过分布式锁确保同一时刻只有一个节点执行 flush。\n * 分布式锁基于 @h-ai/cache 模块实现,运行时通过 cache.isInitialized 动态检测可用性。\n */\nasync function flushPendingMessages(\n providers: Map<string, ReachProvider>,\n repo: SendLogRepository | null,\n): Promise<void> {\n if (!repo) {\n return\n }\n\n // 分布式锁:防止多节点同时 flush\n const FLUSH_LOCK_KEY = 'hai:reach:flush-pending'\n const FLUSH_LOCK_TTL = 60\n let lockAcquired = false\n if (cache.isInitialized) {\n const lockResult = await cache.lock.acquire(FLUSH_LOCK_KEY, { ttl: FLUSH_LOCK_TTL, owner: reachNodeId })\n if (lockResult.success && !lockResult.data) {\n logger.info('Skipping flush, another node holds the lock')\n return\n }\n lockAcquired = lockResult.success && lockResult.data\n }\n\n try {\n const result = await repo.findPending()\n if (!result.success || !result.data.length) {\n return\n }\n\n logger.info('Flushing pending messages', { count: result.data.length })\n\n for (const row of result.data) {\n const provider = providers.get(row.provider)\n if (!provider) {\n logger.warn('Provider not found for pending message, skipping', { provider: row.provider, id: row.id })\n continue\n }\n\n let vars: Record<string, string> | undefined\n let extra: Record<string, unknown> | undefined\n try {\n vars = row.varsJson ? JSON.parse(row.varsJson) as Record<string, string> : undefined\n extra = row.extraJson ? JSON.parse(row.extraJson) as Record<string, unknown> : undefined\n }\n catch {\n logger.warn('Failed to parse pending message JSON, skipping', { id: row.id })\n continue\n }\n\n const message: ReachMessage = {\n provider: row.provider,\n to: row.toAddr,\n subject: row.subject ?? undefined,\n body: row.body ?? undefined,\n template: row.template ?? undefined,\n vars,\n extra,\n }\n\n const sendResult = await provider.send(message)\n if (sendResult.success) {\n await repo.markSent(row.id, sendResult.data.messageId)\n logger.info('Pending message sent', { id: row.id, to: row.toAddr, provider: row.provider })\n }\n else {\n logger.warn('Pending message send failed', { id: row.id, to: row.toAddr, error: sendResult.error.code })\n }\n }\n }\n finally {\n // 释放锁\n if (lockAcquired) {\n await cache.lock.release(FLUSH_LOCK_KEY, reachNodeId).catch((error: unknown) => {\n logger.warn('Failed to release flush lock', { error })\n })\n }\n }\n}\n\n// ─── 发送入口 ───\n\n/**\n * 执行消息发送\n *\n * 包含完整的发送流程:\n * 1. 校验接收方\n * 2. 预处理消息(模板渲染)\n * 3. 检查 DND 免打扰:\n * - discard 策略:返回 DND_BLOCKED 错误\n * - delay 策略:暂存到 DB(pending),返回 deferred 结果\n * 4. 路由到目标 Provider\n * 5. 发送消息\n * 6. 保存发送记录(sent 状态)\n */\nexport async function executeSend(\n message: ReachMessage,\n providers: Map<string, ReachProvider>,\n templateRegistry: ReachTemplateRegistry,\n dndConfig?: DndConfig,\n repo?: SendLogRepository | null,\n): Promise<HaiResult<SendResult>> {\n if (!message.to) {\n return err(\n HaiReachError.INVALID_RECIPIENT,\n reachM('reach_invalidRecipient', { params: { recipient: '' } }),\n )\n }\n\n const preprocessed = await preprocessMessage(message, templateRegistry)\n if (!preprocessed.success) {\n return preprocessed\n }\n\n // 校验 Provider 存在性(在 DND 检查前,确保 delay 也能正确路由)\n const providerName = preprocessed.data.provider\n if (!providerName) {\n return err(\n HaiReachError.PROVIDER_NOT_FOUND,\n reachM('reach_providerRequired'),\n )\n }\n\n if (!providers.has(providerName)) {\n return err(\n HaiReachError.PROVIDER_NOT_FOUND,\n reachM('reach_providerNotFound', { params: { provider: providerName } }),\n )\n }\n\n // DND 检查\n if (isDndBlocked(dndConfig)) {\n const strategy = dndConfig?.strategy ?? 'discard'\n\n if (strategy === 'delay') {\n // delay 策略:暂存消息到 DB\n logger.info('Message deferred by DND (delay strategy)', { provider: providerName, to: message.to })\n try {\n await saveSendRecord(repo ?? null, preprocessed.data, 'pending', providerName)\n }\n catch (error) {\n logger.warn('Failed to save deferred message to DB', { provider: providerName, to: message.to, error })\n return err(\n HaiReachError.SEND_FAILED,\n reachM('reach_dndDeferred'),\n error,\n )\n }\n return ok({ success: true, deferred: true })\n }\n\n // discard 策略:直接拒绝\n logger.info('Message blocked by DND (discard strategy)', { provider: providerName, to: message.to })\n return err(\n HaiReachError.DND_BLOCKED,\n reachM('reach_dndBlocked'),\n )\n }\n\n const provider = providers.get(providerName)!\n\n logger.debug('Sending message', {\n provider: providerName,\n to: preprocessed.data.to,\n template: message.template,\n })\n\n const result = await provider.send(preprocessed.data)\n if (!result.success) {\n logger.warn('Message send failed', {\n provider: providerName,\n to: message.to,\n error: result.error.code,\n })\n return result\n }\n\n // 异步保存发送记录(sent 状态)\n saveSendRecord(repo ?? null, preprocessed.data, 'sent', providerName, result.data.messageId).catch((error) => {\n logger.warn('Failed to save send record', { provider: providerName, to: message.to, error })\n })\n\n return result\n}\n","/**\n * @h-ai/reach — 模板引擎\n *\n * 本文件提供触达模块的模板定义与渲染功能。\n * 所有模板通过数据库持久化存储,避免多节点部署时的状态不一致。\n * @module reach-template\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ReachTemplate, ReachTemplateRegistry, RenderedTemplate } from './reach-types.js'\n\nimport type { TemplateRepository } from './repositories/reach-repository-template.js'\nimport { err, ok } from '@h-ai/core'\n\nimport { reachM } from './reach-i18n.js'\nimport { HaiReachError } from './reach-types.js'\n\n// ─── 变量渲染 ───\n\n/**\n * 将模板字符串中的 `{key}` 占位符替换为实际值\n *\n * @param template - 包含 `{key}` 占位符的模板字符串\n * @param vars - 变量键值对\n * @returns 替换后的字符串\n */\nfunction renderString(template: string, vars: Record<string, string>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key: string) => {\n return Object.prototype.hasOwnProperty.call(vars, key) ? vars[key] : match\n })\n}\n\n/**\n * 渲染模板实体\n */\nfunction renderTemplate(template: ReachTemplate, vars: Record<string, string>): HaiResult<RenderedTemplate> {\n try {\n const rendered: RenderedTemplate = {\n subject: template.subject ? renderString(template.subject, vars) : undefined,\n body: renderString(template.body, vars),\n }\n return ok(rendered)\n }\n catch (error) {\n return err(\n HaiReachError.TEMPLATE_RENDER_FAILED,\n reachM('reach_templateRenderFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n}\n\n// ─── 无数据库时的错误 ───\n\nfunction noDbError(msgKey: 'reach_templateSaveFailed' | 'reach_templateDeleteFailed'): HaiResult<never> {\n return err(\n HaiReachError.SEND_FAILED,\n reachM(msgKey, { params: { error: 'database not available' } }),\n )\n}\n\n// ─── 模板注册表工厂 ───\n\n/**\n * 创建模板注册表\n *\n * @param repo - 可选的数据库模板存储。所有模板操作均通过数据库完成。\n * @returns 模板注册表实例\n *\n * @example\n * ```ts\n * const registry = createTemplateRegistry(templateRepo)\n *\n * await registry.save({\n * name: 'welcome',\n * provider: 'email',\n * subject: '欢迎加入 {appName}',\n * body: '亲爱的 {userName},欢迎使用 {appName}!',\n * })\n *\n * const result = await registry.render('welcome', { appName: 'Hai', userName: '张三' })\n * ```\n */\nexport function createTemplateRegistry(repo?: TemplateRepository | null): ReachTemplateRegistry {\n return {\n async resolve(name: string): Promise<HaiResult<ReachTemplate>> {\n if (!repo) {\n return err(\n HaiReachError.TEMPLATE_NOT_FOUND,\n reachM('reach_templateNotFound', { params: { template: name } }),\n )\n }\n\n const dbResult = await repo.findByName(name)\n if (!dbResult.success) {\n return dbResult\n }\n if (dbResult.data) {\n return ok({\n name: dbResult.data.name,\n provider: dbResult.data.provider,\n subject: dbResult.data.subject ?? undefined,\n body: dbResult.data.body,\n })\n }\n\n return err(\n HaiReachError.TEMPLATE_NOT_FOUND,\n reachM('reach_templateNotFound', { params: { template: name } }),\n )\n },\n\n async save(template: ReachTemplate): Promise<HaiResult<void>> {\n if (!repo) {\n return noDbError('reach_templateSaveFailed')\n }\n return repo.upsert(template)\n },\n\n async saveBatch(templates: ReachTemplate[]): Promise<HaiResult<void>> {\n if (!repo) {\n return noDbError('reach_templateSaveFailed')\n }\n const results = await Promise.all(templates.map(t => repo!.upsert(t)))\n const failed = results.find(r => !r.success)\n if (failed) {\n return failed\n }\n return ok(undefined)\n },\n\n async remove(name: string): Promise<HaiResult<void>> {\n if (!repo) {\n return noDbError('reach_templateDeleteFailed')\n }\n return repo.deleteByName(name)\n },\n\n async list(): Promise<HaiResult<ReachTemplate[]>> {\n if (!repo) {\n return ok([])\n }\n return repo.listTemplates()\n },\n\n async render(name: string, vars: Record<string, string>): Promise<HaiResult<RenderedTemplate>> {\n const resolved = await this.resolve(name)\n if (!resolved.success) {\n return resolved\n }\n return renderTemplate(resolved.data, vars)\n },\n }\n}\n","/**\n * @h-ai/reach — 发送日志存储实现\n *\n * 基于 @h-ai/reldb 的发送日志存储实现。\n * @module reach-repository-send-log\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { DmlWithTxOperations, ReldbCrudFieldDefinition, ReldbCrudRepository, ReldbFunctions } from '@h-ai/reldb'\nimport { err, ok } from '@h-ai/core'\nimport { BaseReldbCrudRepository } from '@h-ai/reldb'\n\nimport { reachM } from '../reach-i18n.js'\nimport { HaiReachError } from '../reach-types.js'\n\n// ─── 发送日志实体类型 ───\n\n/** 发送日志状态 */\nexport type SendLogStatus = 'sent' | 'pending'\n\n/**\n * 发送日志存储实体\n */\nexport interface StoredSendLog {\n /** 自增主键 */\n id: number\n /** Provider 名称 */\n provider: string\n /** 接收方地址 */\n toAddr: string\n /** 邮件主题 */\n subject: string | null\n /** 消息正文 */\n body: string | null\n /** 模板名称 */\n template: string | null\n /** 模板变量 JSON */\n varsJson: string | null\n /** 扩展参数 JSON */\n extraJson: string | null\n /** 发送状态 */\n status: SendLogStatus\n /** Provider 返回的消息 ID */\n messageId: string | null\n /** 创建时间 */\n createdAt: number\n}\n\n// ─── 发送日志存储接口 ───\n\n/**\n * 发送日志存储接口\n */\nexport interface SendLogRepository extends ReldbCrudRepository<StoredSendLog> {\n /**\n * 获取所有待发送记录(按创建时间升序)\n */\n findPending: (tx?: DmlWithTxOperations) => Promise<HaiResult<StoredSendLog[]>>\n\n /**\n * 将记录标记为已发送\n */\n markSent: (id: number, messageId?: string, tx?: DmlWithTxOperations) => Promise<HaiResult<void>>\n}\n\n// ─── 发送日志存储实现 ───\n\n/** 表名 */\nconst TABLE_NAME = 'hai_reach_send_log'\n\n/** 字段定义 */\nconst SEND_LOG_FIELDS: ReldbCrudFieldDefinition[] = [\n {\n fieldName: 'id',\n columnName: 'id',\n def: { type: 'INTEGER' as const, primaryKey: true, autoIncrement: true },\n select: true,\n create: false,\n update: false,\n },\n {\n fieldName: 'provider',\n columnName: 'provider',\n def: { type: 'TEXT' as const, notNull: true },\n select: true,\n create: true,\n update: false,\n },\n {\n fieldName: 'toAddr',\n columnName: 'to_addr',\n def: { type: 'TEXT' as const, notNull: true },\n select: true,\n create: true,\n update: false,\n },\n {\n fieldName: 'subject',\n columnName: 'subject',\n def: { type: 'TEXT' as const },\n select: true,\n create: true,\n update: false,\n },\n {\n fieldName: 'body',\n columnName: 'body',\n def: { type: 'TEXT' as const },\n select: true,\n create: true,\n update: false,\n },\n {\n fieldName: 'template',\n columnName: 'template',\n def: { type: 'TEXT' as const },\n select: true,\n create: true,\n update: false,\n },\n {\n fieldName: 'varsJson',\n columnName: 'vars_json',\n def: { type: 'TEXT' as const },\n select: true,\n create: true,\n update: false,\n },\n {\n fieldName: 'extraJson',\n columnName: 'extra_json',\n def: { type: 'TEXT' as const },\n select: true,\n create: true,\n update: false,\n },\n {\n fieldName: 'status',\n columnName: 'status',\n def: { type: 'TEXT' as const, notNull: true },\n select: true,\n create: true,\n update: true,\n },\n {\n fieldName: 'messageId',\n columnName: 'message_id',\n def: { type: 'TEXT' as const },\n select: true,\n create: true,\n update: true,\n },\n {\n fieldName: 'createdAt',\n columnName: 'created_at',\n def: { type: 'TIMESTAMP' as const, notNull: true },\n select: true,\n create: true,\n update: false,\n },\n]\n\n/** 发送日志存储单例缓存 */\nlet sendLogRepoInstance: SendLogRepository | null = null\nlet sendLogRepoDbConfig: unknown = null\n\n/**\n * 重置发送日志存储单例\n *\n * 在 reach.close() 时调用,释放对旧 db 实例的引用。\n */\nexport function resetSendLogRepoSingleton(): void {\n sendLogRepoInstance = null\n sendLogRepoDbConfig = null\n}\n\n/**\n * 创建基于数据库的发送日志存储实例\n *\n * 单例模式:同一 db 生命周期内重复调用返回缓存实例,\n * db 重新初始化后自动创建新实例。\n *\n * @param db - 数据库服务实例\n * @returns 成功返回发送日志存储接口实现;失败返回含错误信息的 HaiResult\n */\nexport async function createSendLogRepository(db: ReldbFunctions): Promise<HaiResult<SendLogRepository>> {\n if (sendLogRepoInstance && sendLogRepoDbConfig === db.config)\n return ok(sendLogRepoInstance)\n\n const repo = new DbSendLogRepository(db)\n // 触发表创建(BaseReldbCrudRepository 的表创建是异步的)\n const initResult = await repo.count()\n if (!initResult.success) {\n return err(\n HaiReachError.SEND_FAILED,\n reachM('reach_sendFailed', { params: { error: initResult.error.message } }),\n initResult.error,\n )\n }\n sendLogRepoInstance = repo\n sendLogRepoDbConfig = db.config\n return ok(repo)\n}\n\n/**\n * 基于数据库的发送日志存储实现\n */\nclass DbSendLogRepository extends BaseReldbCrudRepository<StoredSendLog> implements SendLogRepository {\n constructor(db: ReldbFunctions) {\n super(db, {\n table: TABLE_NAME,\n fields: SEND_LOG_FIELDS,\n idColumn: 'id',\n idField: 'id',\n createTableIfNotExists: true,\n })\n }\n\n /** 获取所有待发送记录 */\n async findPending(tx?: DmlWithTxOperations): Promise<HaiResult<StoredSendLog[]>> {\n const result = await this.findAll({ where: 'status = ?', params: ['pending'], orderBy: 'created_at ASC' }, tx)\n if (!result.success) {\n return result\n }\n return ok(result.data)\n }\n\n /** 将记录标记为已发送 */\n async markSent(id: number, messageId?: string, tx?: DmlWithTxOperations): Promise<HaiResult<void>> {\n const result = await this.updateById(id, { status: 'sent', messageId: messageId ?? null }, tx)\n if (!result.success) {\n return result\n }\n return ok(undefined)\n }\n}\n","/**\n * @h-ai/reach — 模板存储实现\n *\n * 基于 @h-ai/reldb 的模板持久化存储。\n * 模板支持两种来源:配置文件(config)和数据库(db)。\n * @module reach-repository-template\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { DmlWithTxOperations, ReldbCrudFieldDefinition, ReldbCrudRepository, ReldbFunctions } from '@h-ai/reldb'\n\nimport type { ReachTemplate } from '../reach-types.js'\nimport { err, ok } from '@h-ai/core'\nimport { BaseReldbCrudRepository } from '@h-ai/reldb'\n\nimport { reachM } from '../reach-i18n.js'\nimport { HaiReachError } from '../reach-types.js'\n\n// ─── 模板存储实体类型 ───\n\n/**\n * 数据库模板存储实体\n */\nexport interface StoredTemplate {\n /** 自增主键 */\n id: number\n /** 模板名称(唯一标识) */\n name: string\n /** 绑定的 Provider 名称 */\n provider: string\n /** 邮件主题模板 */\n subject: string | null\n /** 正文模板 */\n body: string\n /** 创建时间 */\n createdAt: number\n /** 更新时间 */\n updatedAt: number\n}\n\n// ─── 模板存储接口 ───\n\n/**\n * 模板存储接口\n */\nexport interface TemplateRepository extends ReldbCrudRepository<StoredTemplate> {\n /**\n * 按名称查找模板\n */\n findByName: (name: string, tx?: DmlWithTxOperations) => Promise<HaiResult<StoredTemplate | undefined>>\n\n /**\n * 保存模板(存在则更新,不存在则插入)\n */\n upsert: (template: ReachTemplate, tx?: DmlWithTxOperations) => Promise<HaiResult<void>>\n\n /**\n * 按名称删除模板\n */\n deleteByName: (name: string, tx?: DmlWithTxOperations) => Promise<HaiResult<void>>\n\n /**\n * 获取所有模板(转换为 ReachTemplate 格式)\n */\n listTemplates: (tx?: DmlWithTxOperations) => Promise<HaiResult<ReachTemplate[]>>\n}\n\n// ─── 模板存储实现 ───\n\n/** 表名 */\nconst TABLE_NAME = 'hai_reach_template'\n\n/** 字段定义 */\nconst TEMPLATE_FIELDS: ReldbCrudFieldDefinition[] = [\n {\n fieldName: 'id',\n columnName: 'id',\n def: { type: 'INTEGER' as const, primaryKey: true, autoIncrement: true },\n select: true,\n create: false,\n update: false,\n },\n {\n fieldName: 'name',\n columnName: 'name',\n def: { type: 'TEXT' as const, notNull: true, unique: true },\n select: true,\n create: true,\n update: true,\n },\n {\n fieldName: 'provider',\n columnName: 'provider',\n def: { type: 'TEXT' as const, notNull: true },\n select: true,\n create: true,\n update: true,\n },\n {\n fieldName: 'subject',\n columnName: 'subject',\n def: { type: 'TEXT' as const },\n select: true,\n create: true,\n update: true,\n },\n {\n fieldName: 'body',\n columnName: 'body',\n def: { type: 'TEXT' as const, notNull: true },\n select: true,\n create: true,\n update: true,\n },\n {\n fieldName: 'createdAt',\n columnName: 'created_at',\n def: { type: 'TIMESTAMP' as const, notNull: true },\n select: true,\n create: true,\n update: false,\n },\n {\n fieldName: 'updatedAt',\n columnName: 'updated_at',\n def: { type: 'TIMESTAMP' as const, notNull: true },\n select: true,\n create: true,\n update: true,\n },\n]\n\n/** 模板存储单例缓存 */\nlet templateRepoInstance: TemplateRepository | null = null\nlet templateRepoDbConfig: unknown = null\n\n/**\n * 重置模板存储单例\n *\n * 在 reach.close() 时调用,释放对旧 db 实例的引用。\n */\nexport function resetTemplateRepoSingleton(): void {\n templateRepoInstance = null\n templateRepoDbConfig = null\n}\n\n/**\n * 创建基于数据库的模板存储实例\n *\n * 单例模式:同一 db 生命周期内重复调用返回缓存实例,\n * db 重新初始化后自动创建新实例。\n *\n * @param db - 数据库服务实例\n * @returns 成功返回模板存储接口实现;失败返回含错误信息的 HaiResult\n */\nexport async function createTemplateRepository(db: ReldbFunctions): Promise<HaiResult<TemplateRepository>> {\n if (templateRepoInstance && templateRepoDbConfig === db.config)\n return ok(templateRepoInstance)\n\n const repo = new DbTemplateRepository(db)\n // 触发表创建(BaseReldbCrudRepository 的表创建是异步的)\n const initResult = await repo.count()\n if (!initResult.success) {\n return err(\n HaiReachError.SEND_FAILED,\n reachM('reach_templateDbInitFailed', { params: { error: initResult.error.message } }),\n initResult.error,\n )\n }\n templateRepoInstance = repo\n templateRepoDbConfig = db.config\n return ok(repo)\n}\n\n/**\n * 将 StoredTemplate 转换为 ReachTemplate\n */\nfunction toReachTemplate(stored: StoredTemplate): ReachTemplate {\n return {\n name: stored.name,\n provider: stored.provider,\n subject: stored.subject ?? undefined,\n body: stored.body,\n }\n}\n\n/**\n * 基于数据库的模板存储实现\n */\nclass DbTemplateRepository extends BaseReldbCrudRepository<StoredTemplate> implements TemplateRepository {\n constructor(db: ReldbFunctions) {\n super(db, {\n table: TABLE_NAME,\n fields: TEMPLATE_FIELDS,\n idColumn: 'id',\n idField: 'id',\n createTableIfNotExists: true,\n })\n }\n\n /** 按名称查找模板 */\n async findByName(name: string, tx?: DmlWithTxOperations): Promise<HaiResult<StoredTemplate | undefined>> {\n const result = await this.findAll({ where: 'name = ?', params: [name], limit: 1 }, tx)\n if (!result.success) {\n return result\n }\n return ok(result.data[0])\n }\n\n /** 保存模板(存在则更新,不存在则插入) */\n async upsert(template: ReachTemplate, tx?: DmlWithTxOperations): Promise<HaiResult<void>> {\n const existing = await this.findByName(template.name, tx)\n if (!existing.success) {\n return existing\n }\n\n const now = Date.now()\n\n if (existing.data) {\n // 更新\n const updateResult = await this.updateById(\n existing.data.id,\n {\n provider: template.provider,\n subject: template.subject ?? null,\n body: template.body,\n updatedAt: now,\n },\n tx,\n )\n if (!updateResult.success) {\n return updateResult\n }\n }\n else {\n // 插入\n const createResult = await this.create(\n {\n name: template.name,\n provider: template.provider,\n subject: template.subject ?? null,\n body: template.body,\n createdAt: now,\n updatedAt: now,\n },\n tx,\n )\n if (!createResult.success) {\n return createResult\n }\n }\n return ok(undefined)\n }\n\n /** 按名称删除模板 */\n async deleteByName(name: string, tx?: DmlWithTxOperations): Promise<HaiResult<void>> {\n const existing = await this.findByName(name, tx)\n if (!existing.success) {\n return existing\n }\n if (!existing.data) {\n return ok(undefined)\n }\n const result = await this.deleteById(existing.data.id, tx)\n if (!result.success) {\n return result\n }\n return ok(undefined)\n }\n\n /** 获取所有模板(转换为 ReachTemplate 格式) */\n async listTemplates(tx?: DmlWithTxOperations): Promise<HaiResult<ReachTemplate[]>> {\n const result = await this.findAll({ orderBy: 'name ASC' }, tx)\n if (!result.success) {\n return result\n }\n return ok(result.data.map(toReachTemplate))\n }\n}\n","/**\n * @h-ai/reach — 触达服务主入口\n *\n * 本文件提供统一的 `reach` 对象,聚合模块生命周期管理。\n * @module reach-main\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ReldbFunctions } from '@h-ai/reldb'\nimport type { DndConfig, ProviderConfig, ReachConfig, ReachConfigInput } from './reach-config.js'\nimport type { ReachFunctions, ReachMessage, ReachProvider, ReachTemplateRegistry, SendResult } from './reach-types.js'\nimport type { SendLogRepository } from './repositories/reach-repository-send-log.js'\nimport type { TemplateRepository } from './repositories/reach-repository-template.js'\n\nimport { core, err, ok } from '@h-ai/core'\n\nimport { createAliyunSmsProvider } from './providers/reach-provider-aliyun-sms.js'\nimport { createApiProvider } from './providers/reach-provider-api.js'\nimport { createConsoleProvider } from './providers/reach-provider-console.js'\nimport { createSmtpProvider } from './providers/reach-provider-smtp.js'\nimport { ReachConfigSchema } from './reach-config.js'\nimport { reachM } from './reach-i18n.js'\nimport { executeSend, resetSendState, startDndScheduler } from './reach-send.js'\nimport { createTemplateRegistry } from './reach-template.js'\nimport {\n HaiReachError,\n\n} from './reach-types.js'\nimport { createSendLogRepository, resetSendLogRepoSingleton } from './repositories/reach-repository-send-log.js'\nimport { createTemplateRepository, resetTemplateRepoSingleton } from './repositories/reach-repository-template.js'\n\nconst logger = core.logger.child({ module: 'reach', scope: 'main' })\n\n// ─── 内部状态 ───\n\n/** 已注册的 Provider 实例(name → Provider) */\nlet providers: Map<string, ReachProvider> = new Map()\n\n/** 当前配置(未初始化时为 null) */\nlet currentConfig: ReachConfig | null = null\n\n/** DND 配置 */\nlet dndConfig: DndConfig | undefined\n\n/** 模板注册表(始终可用) */\nlet templateRegistry: ReachTemplateRegistry = createTemplateRegistry()\n\n/** 发送日志存储(db 可用时初始化) */\nlet sendLogRepo: SendLogRepository | null = null\n\n/** 模板存储(db 可用时初始化) */\nlet templateRepo: TemplateRepository | null = null\n\n/** 初始化进行中标志(防止并发调用) */\nlet initInProgress = false\n\n// ─── Provider 工厂 ───\n\n/**\n * 根据配置创建对应的 Provider\n */\nfunction createProvider(config: ProviderConfig): ReachProvider {\n switch (config.type) {\n case 'console':\n return createConsoleProvider()\n case 'smtp':\n return createSmtpProvider()\n case 'aliyun-sms':\n return createAliyunSmsProvider()\n case 'api':\n return createApiProvider()\n }\n}\n\n// ─── DB 动态引用(可选依赖) ───\n\n/**\n * 尝试获取 db 实例(可选依赖,不可用时返回 null)\n */\nasync function tryGetDb(): Promise<ReldbFunctions | null> {\n try {\n const dbModuleName = '@h-ai/reldb'\n const mod = await (import(/* @vite-ignore */ dbModuleName) as Promise<{ reldb: ReldbFunctions }>)\n if (!mod.reldb.isInitialized) {\n return null\n }\n return mod.reldb\n }\n catch {\n return null\n }\n}\n\n/**\n * 尝试初始化发送日志存储\n */\nasync function tryInitSendLogRepo(): Promise<SendLogRepository | null> {\n try {\n const db = await tryGetDb()\n if (!db) {\n return null\n }\n const result = await createSendLogRepository(db)\n if (!result.success) {\n logger.debug('Send log repository not initialized', { error: result.error.message })\n return null\n }\n return result.data\n }\n catch (error) {\n logger.debug('Send log repository not initialized', { error: error instanceof Error ? error.message : String(error) })\n return null\n }\n}\n\n/**\n * 尝试初始化模板存储\n */\nasync function tryInitTemplateRepo(): Promise<TemplateRepository | null> {\n try {\n const db = await tryGetDb()\n if (!db) {\n return null\n }\n const result = await createTemplateRepository(db)\n if (!result.success) {\n logger.debug('Template repository not initialized', { error: result.error.message })\n return null\n }\n return result.data\n }\n catch (error) {\n logger.debug('Template repository not initialized', { error: error instanceof Error ? error.message : String(error) })\n return null\n }\n}\n\n// ─── 未初始化工具集 ───\n\nconst notInitialized = core.module.createNotInitializedKit(\n HaiReachError.NOT_INITIALIZED,\n () => reachM('reach_notInitialized'),\n)\n\n// ─── 关闭逻辑 ───\n\n/**\n * 关闭所有 Provider 并释放资源(内部实现)\n */\nasync function doClose(): Promise<void> {\n if (providers.size === 0 && currentConfig === null) {\n logger.info('Reach module already closed, skipping')\n return\n }\n\n logger.info('Closing reach module')\n\n for (const [name, provider] of providers.entries()) {\n try {\n await provider.close()\n }\n catch (error) {\n logger.error('Provider close failed', { name, error })\n }\n }\n\n providers = new Map()\n currentConfig = null\n dndConfig = undefined\n templateRegistry = createTemplateRegistry()\n sendLogRepo = null\n templateRepo = null\n resetSendLogRepoSingleton()\n resetTemplateRepoSingleton()\n resetSendState()\n\n logger.info('Reach module closed')\n}\n\n// ─── 初始化逻辑 ───\n\n/**\n * 实际的初始化逻辑(由 init 包裹并发防护后调用)\n */\nasync function doInit(config: ReachConfigInput): Promise<HaiResult<void>> {\n if (providers.size > 0) {\n logger.warn('Reach module is already initialized, reinitializing')\n await doClose()\n }\n\n logger.info('Initializing reach module')\n\n const parseResult = ReachConfigSchema.safeParse(config)\n if (!parseResult.success) {\n logger.error('Reach config validation failed', { error: parseResult.error.message })\n return err(\n HaiReachError.CONFIG_ERROR,\n reachM('reach_configError', { params: { error: parseResult.error.message } }),\n parseResult.error,\n )\n }\n const parsed = parseResult.data\n\n try {\n const newProviders = new Map<string, ReachProvider>()\n\n for (const providerConfig of parsed.providers) {\n const provider = createProvider(providerConfig)\n const connectResult = await provider.connect(providerConfig)\n if (!connectResult.success) {\n logger.error('Provider initialization failed', {\n name: providerConfig.name,\n type: providerConfig.type,\n code: connectResult.error.code,\n message: connectResult.error.message,\n })\n logger.info('Rolling back connected providers', { count: newProviders.size })\n for (const [name, p] of newProviders.entries()) {\n try {\n await p.close()\n }\n catch (rollbackError) {\n logger.error('Provider rollback close failed', { name, error: rollbackError })\n }\n }\n return connectResult\n }\n newProviders.set(providerConfig.name, provider)\n }\n\n providers = newProviders\n currentConfig = parsed\n dndConfig = parsed.dnd\n\n // 尝试初始化模板存储\n templateRepo = await tryInitTemplateRepo()\n\n // 创建模板注册表\n templateRegistry = createTemplateRegistry(templateRepo)\n\n // 配置文件中定义的模板写入数据库\n if (parsed.templates && templateRepo) {\n const saveResult = await templateRegistry.saveBatch(parsed.templates)\n if (!saveResult.success) {\n logger.warn('Failed to save config templates to database', { error: saveResult.error.message })\n }\n }\n\n // 尝试初始化发送日志存储\n sendLogRepo = await tryInitSendLogRepo()\n\n // 启动 DND 恢复定时器\n if (dndConfig) {\n startDndScheduler(dndConfig, providers, sendLogRepo)\n }\n\n const providerNames = parsed.providers.map(p => p.name)\n logger.info('Reach module initialized', { providers: providerNames })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Reach module initialization failed', { error })\n return err(\n HaiReachError.CONFIG_ERROR,\n reachM('reach_initFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n}\n\n// ─── 触达服务对象 ───\n\n/**\n * 触达服务对象\n *\n * 统一的用户触达入口,支持同时使用邮件、短信、API 回调等多种 Provider。\n */\nexport const reach: ReachFunctions = {\n async init(config: ReachConfigInput): Promise<HaiResult<void>> {\n if (initInProgress) {\n logger.warn('Reach module init already in progress, skipping')\n return err(\n HaiReachError.CONFIG_ERROR,\n reachM('reach_configError', { params: { error: 'init already in progress' } }),\n )\n }\n\n initInProgress = true\n try {\n return await doInit(config)\n }\n finally {\n initInProgress = false\n }\n },\n\n async send(message: ReachMessage): Promise<HaiResult<SendResult>> {\n if (providers.size === 0) {\n return notInitialized.result()\n }\n\n return executeSend(message, providers, templateRegistry, dndConfig, sendLogRepo)\n },\n\n get template(): ReachTemplateRegistry {\n return templateRegistry\n },\n\n get config(): ReachConfig | null {\n return currentConfig\n },\n\n get isInitialized(): boolean {\n return providers.size > 0\n },\n\n async close(): Promise<void> {\n await doClose()\n },\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@h-ai/reach",
3
+ "type": "module",
4
+ "version": "0.1.0-alpha5",
5
+ "description": "Hai Framework user reach module for email, SMS, and webhook channels.",
6
+ "license": "Apache-2.0",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "main": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "dependencies": {
23
+ "zod": "^4.3.6",
24
+ "@h-ai/core": "0.1.0-alpha5",
25
+ "@h-ai/reldb": "0.1.0-alpha5",
26
+ "@h-ai/cache": "0.1.0-alpha5"
27
+ },
28
+ "optionalDependencies": {
29
+ "nodemailer": "^8.0.1"
30
+ },
31
+ "devDependencies": {
32
+ "@types/node": "^25.1.0",
33
+ "@types/nodemailer": "^7.0.11",
34
+ "rimraf": "^6.0.1",
35
+ "tsup": "^8.3.5",
36
+ "typescript": "^5.7.2",
37
+ "vitest": "^4.0.18"
38
+ },
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "dev": "tsup --watch",
42
+ "test": "vitest run",
43
+ "test:watch": "vitest",
44
+ "typecheck": "tsc --noEmit",
45
+ "lint": "eslint .",
46
+ "lint:fix": "eslint . --fix",
47
+ "clean": "rimraf dist .turbo"
48
+ }
49
+ }