UNPKG

@lark-project/cli

Version:

飞书项目插件开发工具

72 lines (71 loc) 4.69 kB
"use strict"; 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;