import type { RawSettingValue, SettingInvalid } from "../model/type.js"; /** * 掩码无原值可还原时的拒绝理由(掩码只表达「未修改」,没有原值可还原时它什么也不是)。 * * **写面与草稿测试(dry-run)共用这一句**:id 改名带掩码、无源新频道带掩码是同一种失败,两条链路 * 各写一句迟早漂成两种说法——而「同一份草稿在保存与试发两条路上得到两个答案」正是「掩码搬进 * merge」要消灭的那个缺陷。 * * 事实源放在**写面**这一侧而不是 redact 域:dry-run 已经从这里 import(见 draft/index.ts), * 两句 hints 因此只有一份字面量,跨链路漂移在编译期就不可能发生。 */ export declare const NEW_CHANNEL_MASK_HINT = "\u65B0\u589E\u9891\u9053\u4E0D\u80FD\u63D0\u4EA4\u63A9\u7801\u5360\u4F4D\uFF0C\u8BF7\u586B\u5199\u771F\u5B9E\u51ED\u636E"; /** * 掩码落在**别的 type 的密钥字段名**上时的拒绝理由(跨 type 残留:bark→webhook 后剩一个 * `deviceKey: "********"`)。 * * 与 `NEW_CHANNEL_MASK_HINT` 是**两句话、两种情形**,不许合并:前者是「本 type 的密钥位上没有原值 * 可还原」(新频道 / id 改名),后者是「这个键根本不属于本 type,它属于另一种频道」(换型残留)。 * 合并成一句的后果是把「你该填一个凭据」说成「你贴了一个对不上任何已存值的占位符」——用户在 * 新建频道时看到后一句会以为是自己复制错了。 * * **写面与草稿测试(dry-run)共用这一句**,判据口径也共用:两侧都扫**全部已知类型**的密钥字段名 * (`hasResidualMask` 的扫描面),只扫本 type 的话残留恰恰扫不到——残留的定义就是「字段不属于 * 当前 type」。 */ export declare const RESIDUAL_MASK_HINT = "\u8349\u7A3F\u91CC\u6709\u672A\u8FD8\u539F\u7684\u63A9\u7801\u5360\u4F4D\uFF08\u8DE8\u7C7B\u578B\u6B8B\u7559\u6216\u6539\u540D\u6B8B\u7559\uFF09\uFF0C\u8BF7\u91CD\u65B0\u586B\u5199\u771F\u5B9E\u51ED\u636E"; /** 合并结论。 */ export type ChannelMerge = { readonly ok: true; /** 合并后的频道数组(落盘用;非数组输入原样穿过,形状判据归输入闸门)。 */ readonly channels: RawSettingValue; /** * 与 `channels` **同下标**:该条目里哪些字段的值**原样来自存量**。 * * 这份清单是「写面拒新增、不动存量」的执行依据:只有不在清单里的字段才重新接受合法性 * 判据。少了它,磁盘上一份**越界**的旧值会让此后每一次无关保存都被拒(用户改个名字存不 * 下),而那不是用户造成的。 */ readonly inherited: readonly ReadonlySet[]; /** * 与 `channels` **同下标**:该条目里哪些**必填键是存量本就残缺、这次既没补上也没删掉**的。 * * 它是「半坏条目不许锁死设置页」这条的执行依据(#1016 S3 的一处真实回归):读面自 S3 起不再丢弃 * 半坏条目(视图逐字外发,用户看得见它、也改得动它),而「必填键在场」曾是**绝对**判据,于是 * 用户在升级之后手改出一条半坏条目,此后再改**别的**频道的名字也存不下去(每一次保存都 400)。 * 0.2.9 的形态清理只在刻度推进时跑一次,救不了「升级后手改」这条路。 * * 与 `inherited` 分开记而不并成一条:那条记的是「**值**原样来自存量」,而一个从未存在过的键 * 没有值可沿用。合并成一条,两族判据都说不清自己为什么跳过。 * * 刻意**只记必填键**:其余形状判据(缺 id、type 非法、内置在场)不归它管,故也不受它的放行。 */ readonly preexisting: readonly ReadonlySet[]; } | { readonly ok: false; readonly error: SettingInvalid; }; /** * 合并一个频道数组。 * * @param incoming 提交上来的频道数组(掩码还原**之前**——掩码是本模块的五态之一,不在别处解)。 * @param stored 存量频道数组(磁盘原样)。提交里没提到的键从它取值。 */ export declare function mergeChannels(incoming: RawSettingValue, stored: RawSettingValue): ChannelMerge;