@lark-project/cli
Version:
飞书项目插件开发工具
81 lines (80 loc) • 3.44 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.fillAIPropOptionValues = void 0;
const crypto_1 = require("crypto");
/**
* aiNode / aiField / aiOperation select / multi_select 选项 `value`(webhook 回传的内部值)补全。
*
* value 现在是 schema 声明的**选填**字段,对 AI / 开发者透出:
*
* - AI 填了非空 value → **原样采纳,本函数绝不改它**(哪怕和同 property 内别的选项重复,
* 重复留给 schema 的 `x-unique-fields: ["value"]` 在校验阶段弹出——这是「只做去重校验」
* 的核心:fill 若悄悄改掉重复值,校验就弹不出来了);
* - AI 没填 / 填空串 → 本函数随机补一个 9 位 base36 串(生成时避开同 property 内已用值,
* 不自造重复)。
*
* 由此本模块只负责「补空缺」,不再查远端基线(value 现在是会随配置往返的正常字段,
* 「拉远端 → 改 → set」时 AI 没动的选项会把 value 当普通字段带回原样采纳)。
*
* 补全只发生在 `local-config set`(先于校验 / 后端 dry-run / diff / 落盘,全链路吃同一份),
* 落盘 point.config.local.json 后原样往返、push 时只透传。
*/
const BASE36_ALPHABET = 'abcdefghijklmnopqrstuvwxyz0123456789';
const VALUE_LENGTH = 9; // 对齐 GUI 生成的随机 value 形态(如 brrjos1jw)
const AI_POINT_KEYS = ['aiNode', 'aiField', 'aiOperation'];
function generateOptionValue() {
return Array.from((0, crypto_1.randomBytes)(VALUE_LENGTH), b => BASE36_ALPHABET[b % BASE36_ALPHABET.length]).join('');
}
function asOptionRecords(options) {
if (!Array.isArray(options))
return [];
return options.filter((o) => Boolean(o) && typeof o === 'object');
}
function eachProperty(point, visit) {
if (!point || typeof point !== 'object')
return;
const properties = point.properties;
if (!Array.isArray(properties))
return;
for (const prop of properties) {
if (prop && typeof prop === 'object')
visit(prop);
}
}
function nonEmptyString(v) {
return typeof v === 'string' && v !== '';
}
function fillProperty(prop) {
const options = asOptionRecords(prop.options);
if (!options.length)
return;
// AI 填的非空值原样保留,只用来给后续随机补全避让,**不在此处对重复做任何处理**
// (重复由 schema x-unique-fields 在校验阶段弹)。
const used = new Set();
for (const opt of options) {
if (nonEmptyString(opt.value))
used.add(opt.value);
}
for (const opt of options) {
if (nonEmptyString(opt.value))
continue; // 非空 → 原样采纳,不动
let next;
do {
next = generateOptionValue();
} while (used.has(next));
used.add(next);
opt.value = next;
}
}
/**
* 就地为 config.aiNode / config.aiField / config.aiOperation 下所有选项补全缺失的 value;对其它点位零影响。
* 非空 value 原样保留(含重复——留给校验弹);只有缺失 / 空串才随机补全。
*/
function fillAIPropOptionValues(config) {
if (!config || typeof config !== 'object')
return;
for (const pointKey of AI_POINT_KEYS) {
eachProperty(config[pointKey], fillProperty);
}
}
exports.fillAIPropOptionValues = fillAIPropOptionValues;