UNPKG

@lark-project/cli

Version:

飞书项目插件开发工具

73 lines (72 loc) 4.71 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.initConfigOnlyProject = void 0; const path_1 = __importDefault(require("path")); const fs_extra_1 = require("fs-extra"); const logger_1 = require("../../../utils/logger"); const utils_1 = require("../../../v1/utils"); const local_plugin_config_1 = require("../../../local-plugin-config"); const is_empty_dir_1 = require("../../../utils/is-empty-dir"); const workspace_1 = require("../../utils/workspace"); const resolve_workspace_context_1 = require("../../../utils/resolve-workspace-context"); /** * 为"后端代码在独立仓、没有 plugin.config.json"的开发者建一个 config-only 工作区: * 只写一份最小 plugin.config.json(身份 + app_type + 空 resources),不铺前端代码、不装依赖。 * 之后 `lpm local-config get/set` / `perm` / `update` 都能在它里面跑。 * * 目录名固定为 `meegle-plugin-config`(不接受自定义),让 skill 的 `lpm check context` * 能稳定识别它。幂等:已存在合法 handle 时复用、不覆盖。 */ function initConfigOnlyProject(options, cwd = process.cwd()) { const { pluginId, pluginSecret, siteDomain, appType } = options; const targetDir = path_1.default.join(cwd, resolve_workspace_context_1.BACKEND_HANDLE_DIRNAME); const pluginConfigPath = path_1.default.join(targetDir, 'plugin.config.json'); if ((0, fs_extra_1.existsSync)(pluginConfigPath)) { const existing = (0, fs_extra_1.readJSONSync)(pluginConfigPath); if ((0, local_plugin_config_1.isValidPluginConfig)(existing)[0]) { if (existing.pluginId === pluginId) { logger_1.logger.info(`Config-only workspace already exists at ${targetDir} — reusing it (not overwritten). ` + 'Run `lpm local-config get --remote` inside it to refresh the point config.'); return; } // pluginId 不一致 → 以用户输入为准,清掉旧锚(含旧插件的 .lpm-cache / point.config.local.json) // 给新插件干净重建,避免旧插件的工作态泄漏进新插件的推送。 logger_1.logger.info(`Config-only workspace was for ${existing.pluginId}; re-initializing for ${pluginId} (user input wins).`); (0, fs_extra_1.removeSync)(targetDir); } } if ((0, fs_extra_1.existsSync)(targetDir) && !(0, is_empty_dir_1.isEmptyDir)(targetDir)) { throw new Error(`Target directory "${targetDir}" already exists and is not empty, but has no valid plugin.config.json. ` + 'Refusing to overwrite. Remove it manually and retry, or cd into it if it is already a workspace.'); } (0, fs_extra_1.mkdirpSync)(targetDir); const pluginConfig = { siteDomain, pluginId, pluginSecret: (0, utils_1.encrypt)(pluginSecret), resources: [], app_type: appType, backendOnly: true, }; (0, fs_extra_1.writeJSONSync)(pluginConfigPath, pluginConfig, { spaces: 2 }); (0, workspace_1.ensureWorkspace)(targetDir); (0, workspace_1.ensureGitignore)(targetDir); logger_1.logger.success(`🍻 Config-only workspace created at ${targetDir} (app_type=${appType}).`); // 完整点位配置链路:仅打印到 `get` 会让调用方(尤其 AI agent)误以为读完远端就完事, // 把点位塞进 plugin.config.json 之类的歧路(CLI 不读、永不生效)。这里把"写 + 推"两步显式带出来: // get(读基线) → set --from(校验并写 point.config.local.json,仅本地) → update(推平台)。 // eslint-disable-next-line no-console console.log(`Step 1: cd ${resolve_workspace_context_1.BACKEND_HANDLE_DIRNAME}`); // eslint-disable-next-line no-console console.log('Step 2: lpm local-config get --remote # snapshot current points → .lpm-cache/config/remote.json ({} = none configured yet)'); // eslint-disable-next-line no-console console.log('Step 3: lpm ai init-draft # copy the remote.json baseline above → a draft-*.json (full config), then edit it — `lpm schema` shows the field spec'); // eslint-disable-next-line no-console console.log('Step 4: lpm local-config set --from <draft-*.json> # validate + write point.config.local.json locally (NOT pushed; do NOT hand-edit plugin.config.json for points)'); // eslint-disable-next-line no-console console.log('Step 5: lpm update --source-type=local # push the config to the platform'); } exports.initConfigOnlyProject = initConfigOnlyProject;