@lark-apaas/miaoda-cli 0.1.2 → 0.1.3-alpha.09899c4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +8 -7
  2. package/dist/api/app/api.js +25 -0
  3. package/dist/api/app/index.js +15 -0
  4. package/dist/api/app/schemas.js +79 -0
  5. package/dist/api/app/types.js +58 -0
  6. package/dist/api/db/api.js +390 -55
  7. package/dist/api/db/client.js +65 -25
  8. package/dist/api/db/index.js +12 -1
  9. package/dist/api/db/parsers.js +20 -20
  10. package/dist/api/db/sql-keywords.js +87 -87
  11. package/dist/api/deploy/api.js +60 -0
  12. package/dist/api/deploy/index.js +16 -0
  13. package/dist/api/deploy/schemas.js +105 -0
  14. package/dist/api/deploy/types.js +22 -0
  15. package/dist/api/file/api.js +89 -87
  16. package/dist/api/file/client.js +62 -22
  17. package/dist/api/file/detect.js +3 -3
  18. package/dist/api/file/index.js +2 -1
  19. package/dist/api/file/parsers.js +18 -7
  20. package/dist/api/index.js +7 -1
  21. package/dist/api/observability/api.js +52 -0
  22. package/dist/api/observability/index.js +16 -0
  23. package/dist/api/observability/schemas.js +60 -0
  24. package/dist/api/observability/types.js +27 -0
  25. package/dist/api/plugin/api.js +31 -31
  26. package/dist/cli/commands/app/index.js +62 -0
  27. package/dist/cli/commands/db/index.js +600 -59
  28. package/dist/cli/commands/deploy/index.js +155 -0
  29. package/dist/cli/commands/file/index.js +91 -63
  30. package/dist/cli/commands/index.js +10 -6
  31. package/dist/cli/commands/observability/index.js +240 -0
  32. package/dist/cli/commands/plugin/index.js +27 -27
  33. package/dist/cli/commands/shared.js +86 -10
  34. package/dist/cli/handlers/app/get.js +47 -0
  35. package/dist/cli/handlers/app/index.js +7 -0
  36. package/dist/cli/handlers/app/update.js +59 -0
  37. package/dist/cli/handlers/db/_operator.js +35 -0
  38. package/dist/cli/handlers/db/audit.js +383 -0
  39. package/dist/cli/handlers/db/changelog.js +160 -0
  40. package/dist/cli/handlers/db/data.js +34 -34
  41. package/dist/cli/handlers/db/index.js +17 -1
  42. package/dist/cli/handlers/db/migration.js +245 -0
  43. package/dist/cli/handlers/db/quota.js +68 -0
  44. package/dist/cli/handlers/db/recovery.js +387 -0
  45. package/dist/cli/handlers/db/schema.js +35 -36
  46. package/dist/cli/handlers/db/sql.js +70 -71
  47. package/dist/cli/handlers/deploy/deploy.js +84 -0
  48. package/dist/cli/handlers/deploy/error-log.js +60 -0
  49. package/dist/cli/handlers/deploy/format.js +39 -0
  50. package/dist/cli/handlers/deploy/get.js +71 -0
  51. package/dist/cli/handlers/deploy/helpers.js +41 -0
  52. package/dist/cli/handlers/deploy/history.js +70 -0
  53. package/dist/cli/handlers/deploy/index.js +14 -0
  54. package/dist/cli/handlers/deploy/polling.js +162 -0
  55. package/dist/cli/handlers/file/cp.js +31 -32
  56. package/dist/cli/handlers/file/index.js +3 -1
  57. package/dist/cli/handlers/file/ls.js +6 -7
  58. package/dist/cli/handlers/file/quota.js +66 -0
  59. package/dist/cli/handlers/file/rm.js +33 -32
  60. package/dist/cli/handlers/file/sign.js +4 -5
  61. package/dist/cli/handlers/file/stat.js +11 -11
  62. package/dist/cli/handlers/observability/analytics.js +212 -0
  63. package/dist/cli/handlers/observability/helpers.js +66 -0
  64. package/dist/cli/handlers/observability/index.js +12 -0
  65. package/dist/cli/handlers/observability/log.js +94 -0
  66. package/dist/cli/handlers/observability/metric.js +208 -0
  67. package/dist/cli/handlers/observability/trace.js +102 -0
  68. package/dist/cli/handlers/plugin/plugin-local.js +53 -53
  69. package/dist/cli/handlers/plugin/plugin.js +15 -15
  70. package/dist/cli/help.js +16 -16
  71. package/dist/main.js +13 -9
  72. package/dist/utils/args.js +8 -0
  73. package/dist/utils/colors.js +2 -2
  74. package/dist/utils/config.js +2 -2
  75. package/dist/utils/devops-error.js +28 -0
  76. package/dist/utils/error.js +2 -2
  77. package/dist/utils/git.js +29 -0
  78. package/dist/utils/http.js +119 -1
  79. package/dist/utils/index.js +15 -1
  80. package/dist/utils/output.js +373 -20
  81. package/dist/utils/poll.js +35 -0
  82. package/dist/utils/render.js +27 -27
  83. package/dist/utils/spinner.js +46 -0
  84. package/dist/utils/time.js +208 -0
  85. package/package.json +7 -5
@@ -4,13 +4,13 @@ exports.registerPluginCommands = registerPluginCommands;
4
4
  const index_1 = require("../../../cli/handlers/plugin/index");
5
5
  function registerPluginCommands(program) {
6
6
  const pluginCmd = program
7
- .command("plugin")
8
- .description("插件管理:安装/更新/移除插件包,查询 capability 实例")
9
- .usage("<command> [flags]");
7
+ .command('plugin')
8
+ .description('插件管理:安装/更新/移除插件包,查询 capability 实例')
9
+ .usage('<command> [flags]');
10
10
  pluginCmd.action(() => {
11
11
  pluginCmd.outputHelp();
12
12
  });
13
- pluginCmd.addHelpText("after", `
13
+ pluginCmd.addHelpText('after', `
14
14
  概念
15
15
  - 插件包 (plugin package):.tgz 包,释放到 ./node_modules/<name>
16
16
  - actionPlugins:./package.json 里的字段,记录 { "@scope/name": "version" },作为
@@ -26,10 +26,10 @@ function registerPluginCommands(program) {
26
26
  - remove / list / list-packages:纯本地 FS,不走网络
27
27
  `);
28
28
  pluginCmd
29
- .command("install")
30
- .description("拉取插件包并安装到当前应用项目")
31
- .argument("<names...>", "插件名,格式 @scope/name 或 @scope/name@version;未带版本默认 latest")
32
- .addHelpText("after", `
29
+ .command('install')
30
+ .description('拉取插件包并安装到当前应用项目')
31
+ .argument('<names...>', '插件名,格式 @scope/name 或 @scope/name@version;未带版本默认 latest')
32
+ .addHelpText('after', `
33
33
  行为
34
34
  - 拉取 .tgz 到本地缓存,解压到 ./node_modules/<name>
35
35
  - 在 ./package.json 的 actionPlugins 字段记录 <name>: <version>
@@ -62,10 +62,10 @@ JSON 输出
62
62
  await (0, index_1.handlePluginInstall)({ names });
63
63
  });
64
64
  pluginCmd
65
- .command("update")
66
- .description("把已安装插件升级到 latest 版本")
67
- .argument("<names...>", "插件名,格式 @scope/name;带 @version 也只取 name 部分")
68
- .addHelpText("after", `
65
+ .command('update')
66
+ .description('把已安装插件升级到 latest 版本')
67
+ .argument('<names...>', '插件名,格式 @scope/name;带 @version 也只取 name 部分')
68
+ .addHelpText('after', `
69
69
  行为
70
70
  - 仅对已在 actionPlugins 里的插件生效;未安装的插件返回 notInstalled
71
71
  - 拉取 latest 版本 .tgz,覆盖安装到 ./node_modules/<name>
@@ -97,10 +97,10 @@ JSON 输出
97
97
  await (0, index_1.handlePluginUpdate)({ names });
98
98
  });
99
99
  pluginCmd
100
- .command("remove")
101
- .description("从当前项目移除一个已安装的插件")
102
- .argument("<name>", "插件名,格式 @scope/name")
103
- .addHelpText("after", `
100
+ .command('remove')
101
+ .description('从当前项目移除一个已安装的插件')
102
+ .argument('<name>', '插件名,格式 @scope/name')
103
+ .addHelpText('after', `
104
104
  行为
105
105
  - 删除 ./node_modules/<name> 目录
106
106
  - 从 ./package.json 的 actionPlugins 字段移除对应条目
@@ -123,9 +123,9 @@ JSON 输出
123
123
  (0, index_1.handlePluginRemove)({ name });
124
124
  });
125
125
  pluginCmd
126
- .command("init")
127
- .description("按 package.json 的 actionPlugins 批量安装所有插件")
128
- .addHelpText("after", `
126
+ .command('init')
127
+ .description('按 package.json 的 actionPlugins 批量安装所有插件')
128
+ .addHelpText('after', `
129
129
  行为
130
130
  - 读取 ./package.json 的 actionPlugins,对每个条目按固定版本安装
131
131
  - 已经是目标版本的跳过(幂等),用于 clone 项目后首次同步 / CI
@@ -156,11 +156,11 @@ JSON 输出
156
156
  await (0, index_1.handlePluginInit)();
157
157
  });
158
158
  pluginCmd
159
- .command("list")
160
- .description("列出当前项目的 capability 实例(./server/capabilities/*.json)")
161
- .option("--summary", "不 hydrate(不充血),直接返回 capability 文件的原始 JSON")
162
- .option("--id <id>", "只查询指定 id 的单个 capability")
163
- .addHelpText("after", `
159
+ .command('list')
160
+ .description('列出当前项目的 capability 实例(./server/capabilities/*.json)')
161
+ .option('--summary', '不 hydrate(不充血),直接返回 capability 文件的原始 JSON')
162
+ .option('--id <id>', '只查询指定 id 的单个 capability')
163
+ .addHelpText('after', `
164
164
  行为
165
165
  - 扫描 ./server/capabilities/*.json(排除 capabilities.json)
166
166
  - 默认对每条 capability 做 hydrate:读取 ./node_modules/<pluginKey>/manifest.json,
@@ -190,9 +190,9 @@ JSON 输出
190
190
  await (0, index_1.handlePluginList)(opts);
191
191
  });
192
192
  pluginCmd
193
- .command("list-packages")
194
- .description("列出 package.json actionPlugins 里已声明的插件包")
195
- .addHelpText("after", `
193
+ .command('list-packages')
194
+ .description('列出 package.json actionPlugins 里已声明的插件包')
195
+ .addHelpText('after', `
196
196
  行为
197
197
  - 读取 ./package.json 的 actionPlugins 字段
198
198
  - 只看声明,不校验 ./node_modules 下是否实际存在
@@ -1,11 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.failArgs = void 0;
4
+ exports.appIdOption = appIdOption;
5
+ exports.branchOption = branchOption;
3
6
  exports.softRequiredOption = softRequiredOption;
4
7
  exports.resolveAppId = resolveAppId;
5
8
  exports.withHelp = withHelp;
6
- exports.failArgs = failArgs;
9
+ exports.caseInsensitiveChoice = caseInsensitiveChoice;
10
+ exports.validateTimeOptions = validateTimeOptions;
11
+ exports.rejectCliOverride = rejectCliOverride;
7
12
  const commander_1 = require("commander");
8
13
  const error_1 = require("../../utils/error");
14
+ const time_1 = require("../../utils/time");
15
+ const args_1 = require("../../utils/args");
16
+ Object.defineProperty(exports, "failArgs", { enumerable: true, get: function () { return args_1.failArgs; } });
17
+ /** --app-id option,需要应用上下文的命令自行 .addOption(appIdOption()) */
18
+ function appIdOption() {
19
+ return new commander_1.Option('--app-id <id>', '指定目标应用').env('MIAODA_APP_ID');
20
+ }
21
+ function branchOption() {
22
+ return new commander_1.Option('--branch <branch>', '分支(优先级:--branch > 当前仓库 HEAD 分支;非 git 目录回退应用默认分支)').env('LOCAL_MOCK_MIAODA_DEPLOY_BRANCH');
23
+ }
9
24
  /**
10
25
  * soft-required: Commander 类型上 optional,runtime 校验必填。
11
26
  */
@@ -21,20 +36,24 @@ function softRequiredOption(name, desc) {
21
36
  function resolveAppId(opts) {
22
37
  const id = opts.appId ?? process.env.MIAODA_APP_ID ?? process.env.app_id;
23
38
  if (!id) {
24
- throw new error_1.AppError("APP_ID_MISSING", "未指定应用", {
25
- next_actions: ["设置 export MIAODA_APP_ID=<id>"],
39
+ throw new error_1.AppError('APP_ID_MISSING', '未指定应用', {
40
+ next_actions: ['设置 export MIAODA_APP_ID=<id>'],
26
41
  });
27
42
  }
28
43
  return id;
29
44
  }
30
- /** 包裹 handler,缺 soft-required 参数时打 help 并退出 */
45
+ /**
46
+ * 包裹 handler,缺 soft-required 参数 / 自定义校验失败时打 help 并退出。
47
+ *
48
+ * 兼容带位置参数的 action 签名(如 `(arg1: string, opts) => ...`)。
49
+ */
31
50
  function withHelp(cmd, handler) {
32
- return async (opts) => {
51
+ return async (...args) => {
33
52
  try {
34
- await handler(opts);
53
+ await handler(...args);
35
54
  }
36
55
  catch (err) {
37
- if (err instanceof error_1.AppError && err.code === "ARGS_INVALID") {
56
+ if (err instanceof error_1.AppError && err.code === 'ARGS_INVALID') {
38
57
  process.stderr.write(`Error: ${err.message}\n`);
39
58
  cmd.outputHelp();
40
59
  process.exitCode = 2;
@@ -44,7 +63,64 @@ function withHelp(cmd, handler) {
44
63
  }
45
64
  };
46
65
  }
47
- /** 参数校验失败时抛出,配合 withHelp 自动打 help */
48
- function failArgs(message) {
49
- throw new error_1.AppError("ARGS_INVALID", message);
66
+ /**
67
+ * 大小写不敏感的 choice argParser:把用户输入按 lowerCase 匹配回 canonical 数组里
68
+ * 的同名值(保留 canonical 大小写),未命中抛 Commander 的 InvalidArgumentError
69
+ * (exit code 1,自带友好错误)。
70
+ *
71
+ * 必须先 .choices(canonical)、再 .argParser()——Commander 内部 .choices() 会
72
+ * 重置 parseArg,反过来调会让 argParser 失效。.choices() 仅留给 help 渲染
73
+ * "choices: A, B, C",实际白名单校验由 argParser 接管。
74
+ *
75
+ * new Option("--level <level>", "日志级别(不区分大小写)")
76
+ * .choices(["DEBUG", "INFO", "WARN", "ERROR"])
77
+ * .argParser(caseInsensitiveChoice(["DEBUG", "INFO", "WARN", "ERROR"]));
78
+ */
79
+ function caseInsensitiveChoice(canonical) {
80
+ const map = new Map(canonical.map((v) => [v.toLowerCase(), v]));
81
+ return (raw) => {
82
+ const hit = map.get(raw.toLowerCase());
83
+ if (hit === undefined) {
84
+ throw new commander_1.InvalidArgumentError(`Allowed choices are ${canonical.join(', ')} (case-insensitive).`);
85
+ }
86
+ return hit;
87
+ };
88
+ }
89
+ /**
90
+ * --since / --until 等时间参数的 action 阶段校验。
91
+ *
92
+ * Commander 的 argParser 会在 action 前直接按 parser error 退出(exit 1),
93
+ * 绕过 withHelp 的 ARGS_INVALID → exit 2 路径;所以时间参数在 action 内先
94
+ * 校验一遍,再把原始字符串交给 handler 解析成接口需要的单位。
95
+ */
96
+ function validateTimeOptions(opts, ...names) {
97
+ for (const name of names) {
98
+ const value = opts[name];
99
+ if (value === undefined)
100
+ continue;
101
+ if (typeof value !== 'string') {
102
+ (0, args_1.failArgs)(`--${name.replace(/([A-Z])/g, '-$1').toLowerCase()} 必须是时间字符串`);
103
+ }
104
+ (0, time_1.parseTimeToMs)(value);
105
+ }
106
+ }
107
+ /**
108
+ * 拒绝 CLI 显式覆盖:用于 hideHelp() + .env() 的"沙箱注入参数"(如 --app-id / --branch)。
109
+ *
110
+ * Commander 的 getOptionValueSource() 区分来源(cli / env / default / config / undefined);
111
+ * 用户在 CLI 上显式传时 source === "cli",此时抛 ARGS_INVALID(exit 2 + help)。
112
+ *
113
+ * 用法:在 action 头部一行调用——
114
+ * cmd.action(withHelp(cmd, async (rawOpts) => {
115
+ * rejectCliOverride(cmd, "appId", "branch");
116
+ * ...
117
+ * }));
118
+ */
119
+ function rejectCliOverride(cmd, ...optNames) {
120
+ for (const name of optNames) {
121
+ if (cmd.getOptionValueSource(name) === 'cli') {
122
+ const flag = '--' + name.replace(/([A-Z])/g, '-$1').toLowerCase();
123
+ (0, args_1.failArgs)(`${flag} 由沙箱/本地配置注入,不允许显式传递`);
124
+ }
125
+ }
50
126
  }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.handleAppGet = handleAppGet;
37
+ const api = __importStar(require("../../../api/index"));
38
+ const output_1 = require("../../../utils/output");
39
+ const index_1 = require("../../../api/app/index");
40
+ /** miaoda app get [--app-id <id>] */
41
+ async function handleAppGet(opts) {
42
+ const appID = opts.appId;
43
+ const resp = await api.app.getAppInfo(appID);
44
+ // BAM 在 status_code=0 时 data 字段含 appInfo;不存在则 fallback 空对象
45
+ const meta = resp.appInfo?.appMeta ?? {};
46
+ (0, output_1.emit)({ data: meta }, index_1.appMetaSchema);
47
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleAppUpdate = exports.handleAppGet = void 0;
4
+ var get_1 = require("./get");
5
+ Object.defineProperty(exports, "handleAppGet", { enumerable: true, get: function () { return get_1.handleAppGet; } });
6
+ var update_1 = require("./update");
7
+ Object.defineProperty(exports, "handleAppUpdate", { enumerable: true, get: function () { return update_1.handleAppUpdate; } });
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.handleAppUpdate = handleAppUpdate;
37
+ const api = __importStar(require("../../../api/index"));
38
+ const output_1 = require("../../../utils/output");
39
+ const args_1 = require("../../../utils/args");
40
+ const index_1 = require("../../../api/app/index");
41
+ /** miaoda app update [--app-id <id>] [--name <n>] [--description <d>] */
42
+ async function handleAppUpdate(opts) {
43
+ if (opts.name === undefined && opts.description === undefined) {
44
+ (0, args_1.failArgs)('至少需要 --name 或 --description 中的一个');
45
+ }
46
+ const appID = opts.appId;
47
+ await api.app.updateAppMeta({
48
+ appID,
49
+ name: opts.name,
50
+ description: opts.description,
51
+ });
52
+ // 服务端不回写新 meta,本地再 fetch 一次拿最新值给用户
53
+ const resp = await api.app.getAppInfo(appID);
54
+ const meta = resp.appInfo?.appMeta ?? {};
55
+ if (!(0, output_1.isJsonMode)()) {
56
+ process.stdout.write('✓ App updated successfully\n');
57
+ }
58
+ (0, output_1.emit)({ data: meta }, index_1.appMetaSchema);
59
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ // changelog / audit 共用:把后端透传的 operator 字符串还原成 {id, name}。
3
+ //
4
+ // 后端约定:Operator 字段值是 `{"id":"<user_id>","name":"<resolved_name>"}` JSON
5
+ // 字符串(dataloom inner_service.encodeOperator 生成),用同一字段同时承载机器可
6
+ // 识别的 user_id 与人类可读 name。
7
+ //
8
+ // 选择"字符串内嵌 JSON"而不是 IDL struct,是为了避免 dataloom_inner.thrift +
9
+ // kitex_gen 跨仓库改造;CLI 端 JSON.parse 拆开即可分场景渲染:
10
+ // - --json 模式:返 {id, name} 对象(agent / 下游能区分同名用户)
11
+ // - pretty 模式:只取 name(兼容 PRD 原始 string 形态)
12
+ //
13
+ // 历史数据 / 旧版后端没接这层时,operator 仍是纯字符串。该函数兼容:
14
+ // - 解析失败 → 当作 {id: raw, name: raw}
15
+ // - 解析成功但缺字段 → 用现有字段兜底另一个
16
+ // 解析失败默认不报错,保留 raw 作为兜底显示文本。
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.parseOperator = parseOperator;
19
+ function parseOperator(raw) {
20
+ if (raw === undefined || raw === null || raw === '') {
21
+ return { id: '', name: '' };
22
+ }
23
+ if (!raw.startsWith('{')) {
24
+ return { id: raw, name: raw };
25
+ }
26
+ try {
27
+ const obj = JSON.parse(raw);
28
+ const id = typeof obj.id === 'string' ? obj.id : '';
29
+ const name = typeof obj.name === 'string' && obj.name !== '' ? obj.name : id;
30
+ return { id, name };
31
+ }
32
+ catch {
33
+ return { id: raw, name: raw };
34
+ }
35
+ }