@lark-project/cli
Version:
飞书项目插件开发工具
72 lines (71 loc) • 4.69 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.assertAppTypeMatchesBackend = void 0;
const logger_1 = require("../../../utils/logger");
/**
* publish 用本地 plugin.config.json 的 `app_type` 分流——普通插件走 commitVersion 三步走,
* AI 应用走 release_app 单调用。本地值可能被手改、或人在错的工程目录下执行,一旦和后端
* 真实形态不符,publish 就会串到另一条链路:要么 release_app 发一个普通插件,要么
* commitVersion 发一个 AI 应用——而 CLI 本身没有任何护栏拦得住。
*
* 后端 GetAppDescriptionInfo 响应自带 `app_type`(0 普通 / 1 AI) + `point_types`,publish 本就
* 调这个接口拿元信息(见 ensurePluginMetadataReady),所以这里零额外网络调用即可比对。
*
* 比对策略:
* - 后端没回 `app_type`、或回了 0/1 之外的未知值 → 形态判不出,**fail-fast 抛错拒发**:
* publish 选哪条管道(commitVersion / release_app)全靠 app_type,判不出就只能猜,
* 猜错就把另一类应用发进错管道产生脏数据。宁可拦下也不猜。代价是后端尚无 app_type
* 字段的存量普通插件也会被拦——这是刻意取舍(见对应 commit / 讨论)。
* - 普通 vs AI 跨形态不符 → 抛错拦死。
* - 两边都是 AI 时再按 `point_types` 细分 ai_node / ai_field;`point_types` 缺失或不含
* AI 点位关键字时只能判到「是 AI」这一层,不细分,不阻断——此时 app_type 已确认是 AI,
* ai_node / ai_field 都走同一个 release_app 管道(releaseApp 不消费该子类型),无错管道风险。
*
* 抛出的 Error 由 publishProject 的 catch 统一转成 logger.error + process.exit(1)。
*/
function assertAppTypeMatchesBackend(localAppType, descInfo) {
var _a;
const backendAppType = descInfo.app_type;
// 后端没回、或回了 0/1 之外的未知值 → 形态判不出。publish 选管道全靠 app_type,
// 判不出就只能猜,猜错会把应用发进错管道产生脏数据 → fail-fast 抛错拒发,不猜。
if (backendAppType !== 0 && backendAppType !== 1) {
throw new Error('Cannot confirm app type from the backend: GetAppDescriptionInfo returned ' +
`app_type=${backendAppType === undefined ? 'undefined' : backendAppType}. ` +
'Publishing has to pick a pipeline (normal vs AI) by app_type, and guessing it ' +
'risks releasing into the wrong pipeline and producing dirty data. ' +
'Refusing to publish until the backend reports a recognized app_type (0 or 1). ' +
`Local plugin.config.json declares app_type="${localAppType}".`);
}
const localIsAI = localAppType === 'ai_node' || localAppType === 'ai_field';
const backendIsAI = backendAppType === 1;
if (localIsAI !== backendIsAI) {
throw new Error(`App type mismatch: local plugin.config.json declares app_type="${localAppType}", ` +
`but the backend records this plugin as ${backendIsAI ? 'an AI app' : 'a normal plugin'}. ` +
'Publishing would take the wrong pipeline. ' +
'Check the app_type in plugin.config.json, or make sure you are publishing from the right project directory.');
}
// 两边都是普通插件 → 已对齐
if (!backendIsAI)
return;
// 两边都是 AI → 按 point_types 细分;缺失/不含 AI 关键字时不细分。
// 取首个命中即可:一个 AI 应用恰好一个 ai_node 或一个 ai_field 点位(见 types.ts AppType 注释),
// point_types 不会同时含两者,故 includes 的先后顺序无歧义。
const pointTypes = (_a = descInfo.point_types) !== null && _a !== void 0 ? _a : [];
const backendSpecific = pointTypes.includes('ai_node')
? 'ai_node'
: pointTypes.includes('ai_field')
? 'ai_field'
: undefined;
if (backendSpecific === undefined) {
logger_1.logger.debug(`Backend point_types ambiguous (${JSON.stringify(pointTypes)}); ` +
'skipped the ai_node / ai_field distinction.');
return;
}
if (backendSpecific !== localAppType) {
throw new Error(`App type mismatch: local plugin.config.json declares app_type="${localAppType}", ` +
`but the backend records this plugin as "${backendSpecific}". ` +
'Publishing would take the wrong pipeline. ' +
'Check the app_type in plugin.config.json, or make sure you are publishing from the right project directory.');
}
}
exports.assertAppTypeMatchesBackend = assertAppTypeMatchesBackend;