@lark-project/cli
Version:
飞书项目插件开发工具
141 lines (140 loc) • 8.43 kB
TypeScript
export interface UpdateLocalConfigOptions {
fromPath: string;
/** 显式放行:丢弃 draft 未保留的本地独有未推改动(覆盖前自动备份)。仅 set exit 3 后需要。 */
overwriteLocalEdits?: boolean;
}
export declare const updateLocalConfig: ({ fromPath, overwriteLocalEdits }: UpdateLocalConfigOptions) => Promise<void>;
type PointDiffStatus = 'added' | 'modified' | 'deleted';
/**
* 点位 diff 状态配色:删除红、修改黄、新增默认(不上色)。
* chalk@4 在非 TTY(被 skill 子进程捕获 / jest)下 level=0、原样返回不加 ANSI,
* 故确认块被 AI 转呈时仍是干净文本、测试断言也不受影响——颜色只在终端交互时出现。
*/
export declare function colorizeByStatus(status: PointDiffStatus, text: string): string;
/**
* 一条「点位内部改动」的结构化描述(仅 modified 项填充,纯展示用,删除闸口不读)。
*
* 由 collectStructuralChanges 递归差分产出,覆盖任意深度:
* - `modify`:标量叶子 / 兜底块的 local→remote(`~ path: a → b`)。
* - `add` / `remove`:**带身份字段的数组**里某元素单边出现(local 有→`+`新增、remote 有→`-`删除)。
* - `member`:**纯标量数组**(枚举,如 work_item_type)的成员增删(无"内部修改"概念)。
* path 是按点分路径 + 数组身份下标(`properties[desc013].input_field_types` / `i18n_info.zh-cn.name`)。
*
* 与 modified 判定**同源一致**(都走 fieldCanon / canonicalJson):判为 modified 必有 ≥1 条 change;
* 方案 A 折叠的空兜底字段(空≡缺失)绝不出现。**展示 ≠ 闸口**:删除闸口只读 `removedProperties`,
* 不读这里——这里的 `remove`(含枚举去成员 / i18n 去语言 / DSL 删节点)只"显示"、不触发 exit 2 授权。
*/
export interface StructuralChange {
path: string;
kind: 'modify' | 'add' | 'remove' | 'member';
/** modify:local 侧预览(空≡缺失显示 `(空/缺失)`,全量不截断)。block 时为多行 pretty JSON。 */
local?: string;
remote?: string;
/** member:纯标量数组里 local 多出的成员(推送后会新增)/ remote 多出的成员(推送后会移除)。 */
added?: string[];
removed?: string[];
/** modify 兜底块(无身份数组 / 触深度上限的对象):local/remote 是多行 pretty JSON,按块渲染。 */
block?: boolean;
}
/** @deprecated 旧的扁平字段级明细类型,已被 StructuralChange 取代(保留别名避免外部引用断裂)。 */
export type PointFieldChange = StructuralChange;
export interface PointDiffEntry {
type: string;
key: string;
name?: string;
status: PointDiffStatus;
/**
* 仅 `modified` 项填充:点位内部的结构化改动(任意深度,见 StructuralChange)。
* 与 modified 判定同源——判为 modified 必有 ≥1 条。纯展示用,删除闸口只 filter `status` + 读
* `removedProperties`,不读本字段。
*/
changes?: StructuralChange[];
/**
* 仅 `modified` 项可能填充:remote 有、local 无的**属性**标识(`<array>.<id>`,如
* `properties.foo` / `outputs.bar`)。点位内属性被删 = 不可逆配置丢失,删除闸口读它。
* 非「带属性的点位」(见 PROPERTY_BEARING_TYPES)恒为空。
*/
removedProperties?: string[];
}
/**
* 递归结构化差分:产出「点位内部到任意深度」的改动清单(纯展示,删除闸口不读)。
*
* 规则(与用户拍板的原则一致):
* - 对象 → key 即身份,逐 key 递归;key 单边出现 = 该叶 add/remove,同 key 值变 = 递归 modify。
* - 带身份数组(resolveArrayId 命中)→ 按 id 配对:id 单边 = 元素 add/remove(改名 = 删旧+增新),
* 同 id 内部差异 = 递归进元素。
* - 纯标量数组(枚举)→ 成员增删(member);标量无"内部",故无 modify。
* - 无身份对象数组(DSL 渲染树)/ 触深度上限 → 整块 pretty JSON 兜底(block modify),不再深钻。
* 用 fieldCanon 折叠「空≡缺失」,与 modified 判定同源:返回非空 ⟺ 两端 canonical 不等。
*/
export declare function collectStructuralChanges(local: unknown, remote: unknown, path?: string, depth?: number): StructuralChange[];
/**
* 把一条 StructuralChange 渲染成展示行(可能多行:block 兜底)。`pad` 是行首缩进。
* 标记:`~` 修改 / `+` 新增 / `-` 删除(删除仅"显示",授权见段末「删除授权」块)。
*/
export declare function formatStructuralChange(c: StructuralChange, pad: string): string[];
/** Fetch + reverse-transform the remote plugin config into local-config shape. */
export declare function fetchRemoteConfig(): Promise<Record<string, any>>;
/**
* Diff an arbitrary full config object against the current remote.
* `set` passes the draft (to gate "didn't build on remote → would drop points"),
* `update` / `diff` pass the on-disk `point.config.local.json`.
*/
export declare function computeConfigVsRemoteDiff(local: Record<string, any>): Promise<PointDiffEntry[]>;
/**
* Compare local `point.config.local.json` with remote plugin config.
* Groups by point type + key; classifies each key as added / modified / deleted.
* Used by both `local-config diff` (AI-facing preview) and `update --source-type=local`
* (pre-push deletion gate).
*/
export declare function computeLocalVsRemoteDiff(): Promise<PointDiffEntry[]>;
/**
* 一个 `modified` 点位内部「remote 有、local 无」的属性 / 选项标识列表。
* 格式:属性删除 `<array>.<id>`;保留属性里的选项删除 `<array>.<id>.<nestedArray>.<optId>`。
* 用于删除闸口——点位本身保留、但某个输入属性 / 选项被删掉 = 不可逆配置丢失。
* 改名(旧 key 删 + 新 key 增)会算作旧 key 被删:这是期望行为(rename 对旧配置是破坏性的)。
*/
export declare function computeRemovedProperties(type: string, localItem: any, remoteItem: any): string[];
/** 一条「本地独有、会被 draft 覆盖丢失」的描述(whole=整点位丢失;removedProperties=属性级丢失)。 */
export interface LocalOnlyLossEntry {
type: string;
key: string;
name?: unknown;
whole?: boolean;
removedProperties?: string[];
}
/**
* 算「set 会丢掉的本地独有改动」:draft(D) 相对现存本地文件(L) 丢了什么,再减去远端(R) 已有的部分
* (在 R 的丢失归 deletion gate 管,不重复报)。R 缺省(远端不可达)时不相减,报全部本地丢失项。
* 与 deletion gate 对称:deletion gate 看 D-vs-R 防丢远端;本函数看 D-vs-L 防丢本地未推改动。
* 复用 diffConfigs:`deleted` = 整点位 L 有 D 无;`modified.removedProperties` = 属性 L 有 D 无。
*/
export declare function computeLocalOnlyLoss(draft: Record<string, any>, local: Record<string, any>, remote?: Record<string, any>): LocalOnlyLossEntry[];
/**
* 「本地独有改动会被丢」感知块(stderr,纯文本、无 ANSI,便于弱 AI 逐字转呈)。
* remoteVerified=false(远端不可达)时,把「远端也没有/删除闸口看不到」换成「未核实」说明,
* 避免在没核实远端的情况下做出「这是本地独有」的断言。
*/
export declare function localLossBanner(losses: LocalOnlyLossEntry[], opts?: {
remoteVerified?: boolean;
}): string;
/**
* `lpm local-config diff` entry.
* - stdout: human-readable diff lines
* - stderr (on deletion): DELETION_REQUIRES_CONFIRMATION notice + `<nonce>` (counts point AND property deletions)
* - exit: 0 if no deletions OR deletions already authorized (grant / standing allow);
* 2 if deletions present and NOT authorized; 1 on error
*/
export declare const diffLocalConfig: () => Promise<void>;
interface GetLocalConfigOptions {
remote?: boolean;
compareSnapshot?: boolean;
caseId?: string;
}
/**
* Always writes remote config snapshot to `.lpm-cache/config/remote.json` and
* prints that path on stdout. AI/scripts consume the file, not the JSON blob,
* so conversation context stays clean.
*/
export declare const getLocalConfig: ({ remote, compareSnapshot, caseId, }?: GetLocalConfigOptions) => Promise<unknown>;
export {};