digitalsee-ai-flow-cli 0.6.12-beta → 0.6.15-beta

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 (38) hide show
  1. package/README.md +61 -6
  2. package/dist/api/link.d.ts.map +1 -1
  3. package/dist/api/link.js +4 -0
  4. package/dist/api/link.js.map +1 -1
  5. package/dist/api/mapping.d.ts.map +1 -1
  6. package/dist/api/mapping.js +40 -19
  7. package/dist/api/mapping.js.map +1 -1
  8. package/dist/commands/flow/mapping.d.ts.map +1 -1
  9. package/dist/commands/flow/mapping.js +522 -265
  10. package/dist/commands/flow/mapping.js.map +1 -1
  11. package/dist/commands/flow/node.d.ts.map +1 -1
  12. package/dist/commands/flow/node.js +13 -3
  13. package/dist/commands/flow/node.js.map +1 -1
  14. package/dist/commands/link/account-linking.d.ts.map +1 -0
  15. package/dist/commands/link/account-linking.js +123 -0
  16. package/dist/commands/link/account-linking.js.map +1 -0
  17. package/dist/commands/link/check-mapping.d.ts.map +1 -0
  18. package/dist/commands/link/check-mapping.js +37 -0
  19. package/dist/commands/link/check-mapping.js.map +1 -0
  20. package/dist/commands/link.d.ts.map +1 -1
  21. package/dist/commands/link.js +4 -0
  22. package/dist/commands/link.js.map +1 -1
  23. package/dist/commands/sync/check-mapping.d.ts.map +1 -0
  24. package/dist/commands/sync/check-mapping.js +37 -0
  25. package/dist/commands/sync/check-mapping.js.map +1 -0
  26. package/dist/commands/sync.d.ts.map +1 -1
  27. package/dist/commands/sync.js +2 -0
  28. package/dist/commands/sync.js.map +1 -1
  29. package/dist/index.js +2 -2
  30. package/dist/index.js.map +1 -1
  31. package/dist/types/index.d.ts.map +1 -1
  32. package/dist/utils/output.d.ts.map +1 -1
  33. package/dist/utils/output.js +4 -0
  34. package/dist/utils/output.js.map +1 -1
  35. package/dist/utils/updateCheck.d.ts.map +1 -1
  36. package/dist/utils/updateCheck.js +9 -0
  37. package/dist/utils/updateCheck.js.map +1 -1
  38. package/package.json +1 -1
@@ -2,11 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isMappingSupported = isMappingSupported;
4
4
  exports.getDirectionFromBusinessType = getDirectionFromBusinessType;
5
+ exports.getAvailableSides = getAvailableSides;
5
6
  exports.findMappingByName = findMappingByName;
6
7
  exports.getDirectionLabel = getDirectionLabel;
7
8
  exports.getMappingSubPath = getMappingSubPath;
8
9
  exports.buildMappingEntry = buildMappingEntry;
9
10
  exports.formatMappingMethod = formatMappingMethod;
11
+ exports.filterProfileMappingData = filterProfileMappingData;
12
+ exports.filterBySide = filterBySide;
10
13
  exports.registerFlowMapping = registerFlowMapping;
11
14
  const output_1 = require("@/utils/output");
12
15
  const flow_1 = require("@/api/flow");
@@ -23,6 +26,55 @@ async function validateFlowSupportsMapping(flowId) {
23
26
  }
24
27
  return flow.business_type;
25
28
  }
29
+ const ENTITY_FIELD_MAP = {
30
+ user: {
31
+ label: '用户',
32
+ digParams: 'digUserSubParams',
33
+ digName: 'digUserName',
34
+ otherParams: 'otherUserSubParams',
35
+ otherName: 'otherUserName',
36
+ mappingToIam: 'otherUserMappingToIam',
37
+ mappingToApp: 'otherUserMappingToApp',
38
+ },
39
+ org: {
40
+ label: '部门',
41
+ digParams: 'digOrgSubParams',
42
+ digName: 'digOrgName',
43
+ otherParams: 'otherOrgSubParams',
44
+ otherName: 'otherOrgName',
45
+ mappingToIam: 'otherOrgMappingToIam',
46
+ mappingToApp: 'otherOrgMappingToApp',
47
+ },
48
+ role: {
49
+ label: '角色',
50
+ digParams: 'digRoleSubParams',
51
+ digName: 'digRoleName',
52
+ otherParams: 'otherRoleSubParams',
53
+ otherName: 'otherRoleName',
54
+ mappingToIam: 'otherRoleMappingToIam',
55
+ mappingToApp: 'otherRoleMappingToApp',
56
+ },
57
+ };
58
+ // ── Validation helpers ──────────────────────────────────────
59
+ const VALID_ENTITIES = ['user', 'org', 'role'];
60
+ function validateEntity(entity) {
61
+ if (entity !== undefined && !VALID_ENTITIES.includes(entity)) {
62
+ throw new Error(`无效的实体类型: ${entity},可选值: user | org | role`);
63
+ }
64
+ }
65
+ const VALID_SIDES = ['upstream', 'idaas', 'downstream'];
66
+ function validateSide(side) {
67
+ if (side !== undefined && !VALID_SIDES.includes(side)) {
68
+ throw new Error(`无效的端: ${side},可选值: upstream | idaas | downstream`);
69
+ }
70
+ }
71
+ const VALID_DIRECTIONS = ['all', 'upstream', 'downstream'];
72
+ function validateDirection(direction) {
73
+ if (!VALID_DIRECTIONS.includes(direction)) {
74
+ throw new Error(`无效的方向: ${direction},可选值: upstream | downstream | all`);
75
+ }
76
+ }
77
+ // ── Business type / direction utilities ─────────────────────
26
78
  function getDirectionFromBusinessType(businessType) {
27
79
  if (businessType === 5)
28
80
  return 'upstream';
@@ -30,6 +82,13 @@ function getDirectionFromBusinessType(businessType) {
30
82
  return 'downstream';
31
83
  throw new Error(`不支持的 business_type: ${businessType}`);
32
84
  }
85
+ function getAvailableSides(businessType) {
86
+ if (businessType === 5)
87
+ return ['upstream', 'idaas'];
88
+ if (businessType === 6)
89
+ return ['idaas', 'downstream'];
90
+ return ['upstream', 'idaas', 'downstream'];
91
+ }
33
92
  function findMappingByName(subParams, name, direction) {
34
93
  if (direction === 'upstream') {
35
94
  return subParams.findIndex((item) => item.name === name);
@@ -87,6 +146,93 @@ function buildMappingEntry(sourceField, targetField, method, direction, expressi
87
146
  function formatMappingMethod(item) {
88
147
  return item.update ? 'update' : 'create';
89
148
  }
149
+ function filterProfileMappingData(data, entity, direction) {
150
+ const result = { ...data };
151
+ if (entity && entity !== 'user') {
152
+ result.digUserSubParams = [];
153
+ result.otherUserSubParams = [];
154
+ result.otherUserMappingToIam = [];
155
+ result.otherUserMappingToApp = [];
156
+ }
157
+ if (entity && entity !== 'org') {
158
+ result.digOrgSubParams = [];
159
+ result.otherOrgSubParams = [];
160
+ result.otherOrgMappingToIam = [];
161
+ result.otherOrgMappingToApp = [];
162
+ }
163
+ if (entity && entity !== 'role') {
164
+ result.digRoleSubParams = [];
165
+ result.otherRoleSubParams = [];
166
+ result.otherRoleMappingToIam = [];
167
+ result.otherRoleMappingToApp = [];
168
+ }
169
+ if (direction === 'upstream') {
170
+ result.otherUserMappingToApp = [];
171
+ result.otherOrgMappingToApp = [];
172
+ result.otherRoleMappingToApp = [];
173
+ }
174
+ else if (direction === 'downstream') {
175
+ result.otherUserMappingToIam = [];
176
+ result.otherOrgMappingToIam = [];
177
+ result.otherRoleMappingToIam = [];
178
+ }
179
+ return result;
180
+ }
181
+ function filterBySide(data, side, entity) {
182
+ const result = filterProfileMappingData(data, entity);
183
+ if (side === 'idaas') {
184
+ result.otherUserSubParams = [];
185
+ result.otherOrgSubParams = [];
186
+ result.otherRoleSubParams = [];
187
+ result.otherUserMappingToIam = [];
188
+ result.otherUserMappingToApp = [];
189
+ result.otherOrgMappingToIam = [];
190
+ result.otherOrgMappingToApp = [];
191
+ result.otherRoleMappingToIam = [];
192
+ result.otherRoleMappingToApp = [];
193
+ }
194
+ else if (side === 'upstream') {
195
+ result.otherUserMappingToApp = [];
196
+ result.otherOrgMappingToApp = [];
197
+ result.otherRoleMappingToApp = [];
198
+ result.digUserSubParams = [];
199
+ result.digOrgSubParams = [];
200
+ result.digRoleSubParams = [];
201
+ }
202
+ else if (side === 'downstream') {
203
+ result.otherUserMappingToIam = [];
204
+ result.otherOrgMappingToIam = [];
205
+ result.otherRoleMappingToIam = [];
206
+ result.otherUserSubParams = [];
207
+ result.otherOrgSubParams = [];
208
+ result.otherRoleSubParams = [];
209
+ }
210
+ return result;
211
+ }
212
+ // ── JSON / rendering utilities ──────────────────────────────
213
+ const JSON_FIELD_WHITELIST = new Set([
214
+ 'name',
215
+ 'display_name',
216
+ 'type',
217
+ 'value_type',
218
+ 'value',
219
+ 'update',
220
+ 'source_exp',
221
+ 'target_exp',
222
+ 'exp_type',
223
+ ]);
224
+ function stripMappingItem(item) {
225
+ const out = { name: item.name };
226
+ for (const key of JSON_FIELD_WHITELIST) {
227
+ if (key !== 'name' && item[key] !== undefined && item[key] !== null) {
228
+ out[key] = item[key];
229
+ }
230
+ }
231
+ return out;
232
+ }
233
+ function stripMappingArray(items) {
234
+ return items.map(stripMappingItem);
235
+ }
90
236
  function formatSourceValue(item) {
91
237
  if (item.exp_type === 'JS_EXP' && item.source_exp) {
92
238
  return `JS: ${item.source_exp}`;
@@ -141,78 +287,245 @@ function renderFieldOptions(fields, title) {
141
287
  ]);
142
288
  (0, output_1.printTable)(headers, rows);
143
289
  }
144
- function registerFlowMapping(flowCmd) {
145
- const mappingCmd = flowCmd.command('mapping').description('属性映射管理(账号关联)');
146
- // ── show ────────────────────────────────────────────────
147
- mappingCmd
148
- .command('show <flowId>')
149
- .description('查看属性映射配置')
150
- .option('--type <refType>', '引用类型', 'CONNECTOR')
151
- .option('--mode <mode>', '显示模式: all(全部) | configured(仅已配置) | available(仅可配置项)', 'all')
152
- .option('--json', '以 JSON 格式输出')
153
- .action(async (flowId, options) => {
290
+ function resolveRefType(explicitType, businessType) {
291
+ if (explicitType)
292
+ return explicitType;
293
+ return businessType === 6 ? 'PUSHCONNECTOR' : 'CONNECTOR';
294
+ }
295
+ function wrapAction(errorLabel) {
296
+ return (fn) => async (flowId, options) => {
154
297
  try {
155
298
  if (options.json)
156
299
  (0, output_1.setJsonMode)(true);
157
- const refType = options.type || 'CONNECTOR';
158
- const mode = options.mode || 'all';
159
- await validateFlowSupportsMapping(flowId);
160
- const data = await (0, mapping_1.getProfileMappingData)(flowId, refType);
161
- if (options.json) {
162
- (0, output_1.printJson)(data);
163
- return;
164
- }
165
- (0, output_1.printHeader)(`属性映射配置 (Flow: ${flowId})`);
166
- if (mode === 'all' || mode === 'configured') {
167
- const hasUpstreamMappings = data.otherUserMappingToIam.length > 0 ||
168
- data.otherOrgMappingToIam.length > 0 ||
169
- data.otherRoleMappingToIam.length > 0;
170
- const hasDownstreamMappings = data.otherUserMappingToApp.length > 0 ||
171
- data.otherOrgMappingToApp.length > 0 ||
172
- data.otherRoleMappingToApp.length > 0;
173
- if (!hasUpstreamMappings && !hasDownstreamMappings) {
174
- (0, output_1.printWarning)('暂无已配置的映射');
175
- }
176
- if (hasUpstreamMappings) {
177
- (0, output_1.printHeader)('上游 → IDAAS 映射');
178
- renderMappingTable(data.otherUserMappingToIam, '用户字段映射', 'upstream');
179
- renderMappingTable(data.otherOrgMappingToIam, '部门字段映射', 'upstream');
180
- if (data.otherRoleMappingToIam.length > 0) {
181
- renderMappingTable(data.otherRoleMappingToIam, '角色字段映射', 'upstream');
182
- }
183
- }
184
- if (hasDownstreamMappings) {
185
- (0, output_1.printHeader)('IDAAS → 下游 映射');
186
- renderMappingTable(data.otherUserMappingToApp, '用户字段映射', 'downstream');
187
- renderMappingTable(data.otherOrgMappingToApp, '部门字段映射', 'downstream');
188
- if (data.otherRoleMappingToApp.length > 0) {
189
- renderMappingTable(data.otherRoleMappingToApp, '角色字段映射', 'downstream');
190
- }
191
- }
192
- }
193
- if (mode === 'all' || mode === 'available') {
194
- (0, output_1.printHeader)('可用字段');
195
- renderFieldOptions(data.digUserSubParams, 'IDAAS 用户字段');
196
- renderFieldOptions(data.otherUserSubParams, '上游用户字段');
197
- renderFieldOptions(data.digOrgSubParams, 'IDAAS 部门字段');
198
- renderFieldOptions(data.otherOrgSubParams, '上游部门字段');
199
- if (data.digRoleSubParams.length > 0) {
200
- renderFieldOptions(data.digRoleSubParams, 'IDAAS 角色字段');
201
- }
202
- if (data.otherRoleSubParams.length > 0) {
203
- renderFieldOptions(data.otherRoleSubParams, '上游角色字段');
204
- }
205
- }
300
+ await fn(flowId, options);
206
301
  }
207
302
  catch (error) {
208
303
  if (options.json) {
209
304
  (0, output_1.printStructuredResult)({ ok: false, message: error.message });
210
305
  }
211
306
  else {
212
- (0, output_1.printError)(`获取映射配置失败: ${error.message}`);
307
+ (0, output_1.printError)(`${errorLabel}失败: ${error.message}`);
213
308
  }
214
309
  }
215
- });
310
+ };
311
+ }
312
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
313
+ function parseShowOptions(options) {
314
+ const refType = options.type;
315
+ const mode = options.mode || 'all';
316
+ const entity = options.entity;
317
+ const side = options.side;
318
+ const direction = side ? 'all' : (options.direction || 'all');
319
+ if (side && options.direction && options.direction !== 'all') {
320
+ throw new Error('--side 与 --direction 互斥,不能同时使用');
321
+ }
322
+ validateEntity(entity);
323
+ validateSide(side);
324
+ validateDirection(direction);
325
+ return { refType, mode, entity, side, direction };
326
+ }
327
+ async function prepareShowData(flowId, params) {
328
+ const businessType = await validateFlowSupportsMapping(flowId);
329
+ const refType = resolveRefType(params.refType, businessType);
330
+ const availableSides = getAvailableSides(businessType);
331
+ if (params.side && !availableSides.includes(params.side)) {
332
+ const btLabel = businessType === 5 ? '通讯录集成' : '通讯录同步';
333
+ throw new Error(`该流为${btLabel},不支持 --side ${params.side},可用: ${availableSides.join(' | ')}`);
334
+ }
335
+ // 按需获取:避免请求不需要的数据
336
+ const needsDig = params.mode !== 'configured' || params.side === 'idaas';
337
+ const needsConnector = params.side !== 'idaas';
338
+ const [dig, raw] = await Promise.all([
339
+ needsDig ? (0, mapping_1.getDigProfileTemplates)(refType) : null,
340
+ needsConnector ? (0, mapping_1.fetchProfileData)(flowId, refType) : null,
341
+ ]);
342
+ const data = (0, mapping_1.buildProfileMappingData)(dig, raw);
343
+ // Auto-filter based on flow type when no --side specified
344
+ if (!params.side) {
345
+ if (businessType === 5) {
346
+ data.otherUserMappingToApp = [];
347
+ data.otherOrgMappingToApp = [];
348
+ data.otherRoleMappingToApp = [];
349
+ }
350
+ else if (businessType === 6) {
351
+ data.otherUserMappingToIam = [];
352
+ data.otherOrgMappingToIam = [];
353
+ data.otherRoleMappingToIam = [];
354
+ data.otherUserSubParams = [];
355
+ data.otherOrgSubParams = [];
356
+ data.otherRoleSubParams = [];
357
+ }
358
+ }
359
+ const filtered = params.side
360
+ ? filterBySide(data, params.side, params.entity)
361
+ : filterProfileMappingData(data, params.entity, params.direction);
362
+ return { filtered, businessType };
363
+ }
364
+ function printShowJsonOutput(filtered, mode) {
365
+ const jsonData = {};
366
+ const showAvailable = mode === 'all' || mode === 'available';
367
+ const showConfigured = mode === 'all' || mode === 'configured';
368
+ if (showAvailable) {
369
+ for (const fm of Object.values(ENTITY_FIELD_MAP)) {
370
+ const dig = filtered[fm.digParams];
371
+ const other = filtered[fm.otherParams];
372
+ if (dig.length > 0) {
373
+ jsonData[fm.digParams] = stripMappingArray(dig);
374
+ jsonData[fm.digName] = filtered[fm.digName];
375
+ }
376
+ if (other.length > 0) {
377
+ jsonData[fm.otherParams] = stripMappingArray(other);
378
+ jsonData[fm.otherName] = filtered[fm.otherName];
379
+ }
380
+ }
381
+ }
382
+ if (showConfigured) {
383
+ for (const fm of Object.values(ENTITY_FIELD_MAP)) {
384
+ for (const key of [fm.mappingToIam, fm.mappingToApp]) {
385
+ const arr = filtered[key];
386
+ if (arr.length > 0)
387
+ jsonData[key] = stripMappingArray(arr);
388
+ }
389
+ }
390
+ }
391
+ (0, output_1.printJson)(jsonData);
392
+ }
393
+ // ── Show command rendering helpers ──────────────────────────
394
+ function entityMatches(filter, entityType) {
395
+ return !filter || filter === entityType;
396
+ }
397
+ function renderIdaaAvailableFields(filtered, entity) {
398
+ for (const [et, fm] of Object.entries(ENTITY_FIELD_MAP)) {
399
+ if (!entityMatches(entity, et))
400
+ continue;
401
+ renderFieldOptions(filtered[fm.digParams], `IDAAS ${fm.label}字段: ${filtered[fm.digName]}`);
402
+ }
403
+ }
404
+ function renderConfiguredMappings(filtered, side, entity, direction) {
405
+ if (side === 'idaas') {
406
+ (0, output_1.printWarning)('IDAAS 端无已配置映射(IDAAS 端仅包含字段模板,使用 --mode available 查看)');
407
+ return;
408
+ }
409
+ if (side === 'upstream') {
410
+ for (const [et, fm] of Object.entries(ENTITY_FIELD_MAP)) {
411
+ if (!entityMatches(entity, et))
412
+ continue;
413
+ const items = filtered[fm.mappingToIam];
414
+ if (items.length > 0)
415
+ renderMappingTable(items, `${fm.label}字段映射`, 'upstream');
416
+ }
417
+ return;
418
+ }
419
+ if (side === 'downstream') {
420
+ for (const [et, fm] of Object.entries(ENTITY_FIELD_MAP)) {
421
+ if (!entityMatches(entity, et))
422
+ continue;
423
+ const items = filtered[fm.mappingToApp];
424
+ if (items.length > 0)
425
+ renderMappingTable(items, `${fm.label}字段映射`, 'downstream');
426
+ }
427
+ return;
428
+ }
429
+ // No side filter: render both upstream and downstream sections
430
+ const showUpstream = direction === 'all' || direction === 'upstream';
431
+ const showDownstream = direction === 'all' || direction === 'downstream';
432
+ const hasUpstream = showUpstream &&
433
+ Object.entries(ENTITY_FIELD_MAP).some(([et, fm]) => entityMatches(entity, et) &&
434
+ filtered[fm.mappingToIam].length > 0);
435
+ const hasDownstream = showDownstream &&
436
+ Object.entries(ENTITY_FIELD_MAP).some(([et, fm]) => entityMatches(entity, et) &&
437
+ filtered[fm.mappingToApp].length > 0);
438
+ if (!hasUpstream && !hasDownstream) {
439
+ (0, output_1.printWarning)('暂无已配置的映射');
440
+ }
441
+ if (hasUpstream) {
442
+ (0, output_1.printHeader)('上游 → IDAAS 映射');
443
+ for (const [et, fm] of Object.entries(ENTITY_FIELD_MAP)) {
444
+ if (!entityMatches(entity, et))
445
+ continue;
446
+ const items = filtered[fm.mappingToIam];
447
+ if (items.length > 0)
448
+ renderMappingTable(items, `${fm.label}字段映射`, 'upstream');
449
+ }
450
+ }
451
+ if (hasDownstream) {
452
+ (0, output_1.printHeader)('IDAAS → 下游 映射');
453
+ for (const [et, fm] of Object.entries(ENTITY_FIELD_MAP)) {
454
+ if (!entityMatches(entity, et))
455
+ continue;
456
+ const items = filtered[fm.mappingToApp];
457
+ if (items.length > 0)
458
+ renderMappingTable(items, `${fm.label}字段映射`, 'downstream');
459
+ }
460
+ }
461
+ }
462
+ function renderAvailableFields(filtered, entity, isFocused, mode, side) {
463
+ if (isFocused && mode === 'all')
464
+ return;
465
+ (0, output_1.printHeader)('可用字段');
466
+ const digLabel = side === 'downstream' ? '下游' : 'IDAAS';
467
+ for (const [et, fm] of Object.entries(ENTITY_FIELD_MAP)) {
468
+ if (!entityMatches(entity, et))
469
+ continue;
470
+ const digFields = filtered[fm.digParams];
471
+ const otherFields = filtered[fm.otherParams];
472
+ if (digFields.length > 0) {
473
+ renderFieldOptions(digFields, `${digLabel} ${fm.label}字段: ${filtered[fm.digName]}`);
474
+ }
475
+ if (otherFields.length > 0) {
476
+ renderFieldOptions(otherFields, `上游${fm.label}字段: ${filtered[fm.otherName]}`);
477
+ }
478
+ }
479
+ }
480
+ // ── Command registration ────────────────────────────────────
481
+ function registerFlowMapping(flowCmd) {
482
+ const mappingCmd = flowCmd.command('mapping').description('属性映射管理(账号关联)');
483
+ // ── show ────────────────────────────────────────────────
484
+ mappingCmd
485
+ .command('show <flowId>')
486
+ .description('查看属性映射配置')
487
+ .option('--entity <entity>', '实体类型过滤: user | org | role')
488
+ .option('--side <side>', '聚焦端: upstream(上游端) | idaas(IDAAS端) | downstream(下游端)。与 --direction 互斥')
489
+ .option('--direction <direction>', '方向过滤: upstream(上游→IDAAS) | downstream(IDAAS→下游) | all(全部)', 'all')
490
+ .option('--mode <mode>', '显示模式: all(全部) | configured(仅已配置) | available(仅可配置项)', 'all')
491
+ .option('--json', '以 JSON 格式输出')
492
+ .action(wrapAction('获取映射配置')(async (flowId, options) => {
493
+ const params = parseShowOptions(options);
494
+ const { filtered } = await prepareShowData(flowId, params);
495
+ if (options.json) {
496
+ printShowJsonOutput(filtered, params.mode);
497
+ return;
498
+ }
499
+ // Title
500
+ const titleParts = [];
501
+ if (params.side) {
502
+ const sideLabels = {
503
+ upstream: '上游端',
504
+ idaas: 'IDAAS端',
505
+ downstream: '下游端',
506
+ };
507
+ titleParts.push(sideLabels[params.side]);
508
+ }
509
+ if (params.entity) {
510
+ const entityLabels = { user: '用户', org: '部门', role: '角色' };
511
+ titleParts.push(entityLabels[params.entity]);
512
+ }
513
+ const title = titleParts.length > 0
514
+ ? `${titleParts.join('')}映射配置 (Flow: ${flowId})`
515
+ : `属性映射配置 (Flow: ${flowId})`;
516
+ (0, output_1.printHeader)(title);
517
+ const isFocused = !!(params.entity && (params.side || params.direction !== 'all'));
518
+ if (params.side === 'idaas' && (params.mode === 'all' || params.mode === 'available')) {
519
+ renderIdaaAvailableFields(filtered, params.entity);
520
+ return;
521
+ }
522
+ if (params.mode === 'all' || params.mode === 'configured') {
523
+ renderConfiguredMappings(filtered, params.side, params.entity, params.direction);
524
+ }
525
+ if (params.mode === 'all' || params.mode === 'available') {
526
+ renderAvailableFields(filtered, params.entity, isFocused, params.mode, params.side);
527
+ }
528
+ }));
216
529
  // ── add ─────────────────────────────────────────────────
217
530
  mappingCmd
218
531
  .command('add <flowId>')
@@ -225,65 +538,50 @@ function registerFlowMapping(flowCmd) {
225
538
  .option('--method <method>', '映射方式: create | update', 'create')
226
539
  .option('--type <refType>', '引用类型', 'CONNECTOR')
227
540
  .option('--json', '以 JSON 格式输出')
228
- .action(async (flowId, options) => {
229
- try {
230
- if (options.json)
231
- (0, output_1.setJsonMode)(true);
232
- const refType = options.type || 'CONNECTOR';
233
- const businessType = await validateFlowSupportsMapping(flowId);
234
- const direction = getDirectionFromBusinessType(businessType);
235
- const entity = options.entity;
236
- if (!['user', 'org', 'role'].includes(entity)) {
237
- throw new Error(`无效的实体类型: ${entity},可选值: user | org | role`);
238
- }
239
- if (options.sourceField && options.expression) {
240
- throw new Error('--source-field 与 --expression 互斥,请只提供其中一个');
241
- }
242
- if (!options.sourceField && !options.expression) {
243
- throw new Error('必须提供 --source-field 或 --expression');
244
- }
245
- if (options.targetField && options.targetExpression) {
246
- throw new Error('--target-field 与 --target-expression 互斥,请只提供其中一个');
247
- }
248
- if (!options.targetField && !options.targetExpression) {
249
- throw new Error('必须提供 --target-field 或 --target-expression');
250
- }
251
- const method = options.method === 'update' ? 'update' : 'create';
252
- const profileData = await (0, mapping_1.fetchProfileData)(flowId, refType);
253
- const subParams = ensureSubParams(profileData, entity, direction);
254
- // IDAAS 侧标识检查重名
255
- const idaasKey = options.targetField || options.targetExpression;
256
- const existing = subParams.find((item) => direction === 'upstream' ? item.name === idaasKey : item.value === idaasKey);
257
- if (existing && !options.targetExpression) {
258
- throw new Error(`映射已存在: ${idaasKey},如需修改请使用 flow mapping set 命令`);
259
- }
260
- const sourceField = options.sourceField || options.expression;
261
- const targetField = options.targetField || options.targetExpression;
262
- const entry = buildMappingEntry(sourceField, targetField, method, direction, options.expression, options.targetExpression);
263
- subParams.push(entry);
264
- await (0, mapping_1.editMapping)(flowId, refType, profileData);
265
- if (options.json) {
266
- (0, output_1.printJson)({ ok: true, message: '映射已添加', entry, flowId });
267
- }
268
- else {
269
- const sourceLabel = options.expression
270
- ? `JS: ${options.expression}`
271
- : options.sourceField;
272
- const targetLabel = options.targetExpression
273
- ? `JS: ${options.targetExpression}`
274
- : options.targetField;
275
- (0, output_1.printSuccess)(`映射已添加 (${getDirectionLabel(direction)}): ${sourceLabel} → ${targetLabel} (${method})`);
276
- }
541
+ .action(wrapAction('添加映射')(async (flowId, options) => {
542
+ const entity = options.entity;
543
+ validateEntity(entity);
544
+ if (options.sourceField && options.expression) {
545
+ throw new Error('--source-field 与 --expression 互斥,请只提供其中一个');
277
546
  }
278
- catch (error) {
279
- if (options.json) {
280
- (0, output_1.printStructuredResult)({ ok: false, message: error.message });
281
- }
282
- else {
283
- (0, output_1.printError)(`添加映射失败: ${error.message}`);
284
- }
547
+ if (!options.sourceField && !options.expression) {
548
+ throw new Error('必须提供 --source-field 或 --expression');
285
549
  }
286
- });
550
+ if (options.targetField && options.targetExpression) {
551
+ throw new Error('--target-field 与 --target-expression 互斥,请只提供其中一个');
552
+ }
553
+ if (!options.targetField && !options.targetExpression) {
554
+ throw new Error('必须提供 --target-field 或 --target-expression');
555
+ }
556
+ const businessType = await validateFlowSupportsMapping(flowId);
557
+ const direction = getDirectionFromBusinessType(businessType);
558
+ const method = options.method === 'update' ? 'update' : 'create';
559
+ const refType = resolveRefType(options.type, businessType);
560
+ const profileData = await (0, mapping_1.fetchProfileData)(flowId, refType);
561
+ const subParams = ensureSubParams(profileData, entity, direction);
562
+ const idaasKey = options.targetField || options.targetExpression;
563
+ const existing = subParams.find((item) => direction === 'upstream' ? item.name === idaasKey : item.value === idaasKey);
564
+ if (existing && !options.targetExpression) {
565
+ throw new Error(`映射已存在: ${idaasKey},如需修改请使用 flow mapping set 命令`);
566
+ }
567
+ const sourceField = options.sourceField || options.expression;
568
+ const targetField = options.targetField || options.targetExpression;
569
+ const entry = buildMappingEntry(sourceField, targetField, method, direction, options.expression, options.targetExpression);
570
+ subParams.push(entry);
571
+ await (0, mapping_1.editMapping)(flowId, refType, profileData);
572
+ if (options.json) {
573
+ (0, output_1.printJson)({ ok: true, message: '映射已添加', entry, flowId });
574
+ }
575
+ else {
576
+ const sourceLabel = options.expression
577
+ ? `JS: ${options.expression}`
578
+ : options.sourceField;
579
+ const targetLabel = options.targetExpression
580
+ ? `JS: ${options.targetExpression}`
581
+ : options.targetField;
582
+ (0, output_1.printSuccess)(`映射已添加 (${getDirectionLabel(direction)}): ${sourceLabel} → ${targetLabel} (${method})`);
583
+ }
584
+ }));
287
585
  // ── set ─────────────────────────────────────────────────
288
586
  mappingCmd
289
587
  .command('set <flowId>')
@@ -297,101 +595,87 @@ function registerFlowMapping(flowCmd) {
297
595
  .option('--method <method>', '映射方式: create | update')
298
596
  .option('--type <refType>', '引用类型', 'CONNECTOR')
299
597
  .option('--json', '以 JSON 格式输出')
300
- .action(async (flowId, options) => {
301
- try {
302
- if (options.json)
303
- (0, output_1.setJsonMode)(true);
304
- const refType = options.type || 'CONNECTOR';
305
- const businessType = await validateFlowSupportsMapping(flowId);
306
- const direction = getDirectionFromBusinessType(businessType);
307
- const entity = options.entity;
308
- if (!['user', 'org', 'role'].includes(entity)) {
309
- throw new Error(`无效的实体类型: ${entity},可选值: user | org | role`);
310
- }
311
- if (options.sourceField && options.expression) {
312
- throw new Error('--source-field 与 --expression 互斥,请只提供其中一个');
313
- }
314
- if (options.targetField && options.targetExpression) {
315
- throw new Error('--target-field 与 --target-expression 互斥,请只提供其中一个');
316
- }
317
- if (!options.sourceField &&
318
- !options.expression &&
319
- !options.targetField &&
320
- !options.targetExpression &&
321
- !options.method) {
322
- throw new Error('至少需要提供一个修改项');
323
- }
324
- const profileData = await (0, mapping_1.fetchProfileData)(flowId, refType);
325
- const subParams = getSubParams(profileData, entity, direction);
326
- const idx = findMappingByName(subParams, options.name, direction);
327
- if (idx === -1) {
328
- throw new Error(`未找到映射: ${options.name}`);
329
- }
330
- const entry = subParams[idx];
331
- const oldEntry = { ...entry };
332
- if (options.sourceField !== undefined) {
333
- if (direction === 'upstream') {
334
- entry.value = options.sourceField;
335
- }
336
- else {
337
- entry.name = options.sourceField;
338
- }
339
- delete entry.source_exp;
340
- if (!entry.target_exp)
341
- delete entry.exp_type;
342
- }
343
- if (options.expression !== undefined) {
344
- if (direction === 'upstream') {
345
- entry.value = options.expression;
346
- }
347
- else {
348
- entry.name = options.expression;
349
- }
350
- entry.source_exp = options.expression;
351
- entry.exp_type = 'JS_EXP';
598
+ .action(wrapAction('修改映射')(async (flowId, options) => {
599
+ const entity = options.entity;
600
+ validateEntity(entity);
601
+ if (options.sourceField && options.expression) {
602
+ throw new Error('--source-field 与 --expression 互斥,请只提供其中一个');
603
+ }
604
+ if (options.targetField && options.targetExpression) {
605
+ throw new Error('--target-field 与 --target-expression 互斥,请只提供其中一个');
606
+ }
607
+ if (!options.sourceField &&
608
+ !options.expression &&
609
+ !options.targetField &&
610
+ !options.targetExpression &&
611
+ !options.method) {
612
+ throw new Error('至少需要提供一个修改项');
613
+ }
614
+ const businessType = await validateFlowSupportsMapping(flowId);
615
+ const direction = getDirectionFromBusinessType(businessType);
616
+ const refType = resolveRefType(options.type, businessType);
617
+ const profileData = await (0, mapping_1.fetchProfileData)(flowId, refType);
618
+ const subParams = getSubParams(profileData, entity, direction);
619
+ const idx = findMappingByName(subParams, options.name, direction);
620
+ if (idx === -1) {
621
+ throw new Error(`未找到映射: ${options.name}`);
622
+ }
623
+ const entry = subParams[idx];
624
+ const oldEntry = { ...entry };
625
+ if (options.sourceField !== undefined) {
626
+ if (direction === 'upstream') {
627
+ entry.value = options.sourceField;
352
628
  }
353
- if (options.targetField !== undefined) {
354
- if (direction === 'upstream') {
355
- entry.name = options.targetField;
356
- }
357
- else {
358
- entry.value = options.targetField;
359
- }
360
- delete entry.target_exp;
361
- if (!entry.source_exp)
362
- delete entry.exp_type;
629
+ else {
630
+ entry.name = options.sourceField;
363
631
  }
364
- if (options.targetExpression !== undefined) {
365
- if (direction === 'upstream') {
366
- entry.name = options.targetExpression;
367
- }
368
- else {
369
- entry.value = options.targetExpression;
370
- }
371
- entry.target_exp = options.targetExpression;
372
- entry.exp_type = 'JS_EXP';
632
+ delete entry.source_exp;
633
+ if (!entry.target_exp)
634
+ delete entry.exp_type;
635
+ }
636
+ if (options.expression !== undefined) {
637
+ if (direction === 'upstream') {
638
+ entry.value = options.expression;
373
639
  }
374
- if (options.method !== undefined) {
375
- entry.update = options.method === 'update';
640
+ else {
641
+ entry.name = options.expression;
376
642
  }
377
- subParams[idx] = entry;
378
- await (0, mapping_1.editMapping)(flowId, refType, profileData);
379
- if (options.json) {
380
- (0, output_1.printJson)({ ok: true, message: '映射已更新', old: oldEntry, updated: entry, flowId });
643
+ entry.source_exp = options.expression;
644
+ entry.exp_type = 'JS_EXP';
645
+ }
646
+ if (options.targetField !== undefined) {
647
+ if (direction === 'upstream') {
648
+ entry.name = options.targetField;
381
649
  }
382
650
  else {
383
- (0, output_1.printSuccess)(`映射已更新: ${options.name}`);
651
+ entry.value = options.targetField;
384
652
  }
653
+ delete entry.target_exp;
654
+ if (!entry.source_exp)
655
+ delete entry.exp_type;
385
656
  }
386
- catch (error) {
387
- if (options.json) {
388
- (0, output_1.printStructuredResult)({ ok: false, message: error.message });
657
+ if (options.targetExpression !== undefined) {
658
+ if (direction === 'upstream') {
659
+ entry.name = options.targetExpression;
389
660
  }
390
661
  else {
391
- (0, output_1.printError)(`修改映射失败: ${error.message}`);
662
+ entry.value = options.targetExpression;
392
663
  }
664
+ entry.target_exp = options.targetExpression;
665
+ entry.exp_type = 'JS_EXP';
393
666
  }
394
- });
667
+ if (options.method !== undefined) {
668
+ entry.update = options.method === 'update';
669
+ }
670
+ subParams[idx] = entry;
671
+ await (0, mapping_1.editMapping)(flowId, refType, profileData);
672
+ if (options.json) {
673
+ (0, output_1.printJson)({ ok: true, message: '映射已更新', old: oldEntry, updated: entry, flowId });
674
+ }
675
+ else {
676
+ (0, output_1.printSuccess)(`映射已更新: ${options.name}`);
677
+ }
678
+ }));
395
679
  // ── delete ──────────────────────────────────────────────
396
680
  mappingCmd
397
681
  .command('delete <flowId>')
@@ -400,78 +684,51 @@ function registerFlowMapping(flowCmd) {
400
684
  .requiredOption('--name <fieldName>', 'IDAAS 字段名,用于定位映射条目')
401
685
  .option('--type <refType>', '引用类型', 'CONNECTOR')
402
686
  .option('--json', '以 JSON 格式输出')
403
- .action(async (flowId, options) => {
404
- try {
405
- if (options.json)
406
- (0, output_1.setJsonMode)(true);
407
- const refType = options.type || 'CONNECTOR';
408
- const businessType = await validateFlowSupportsMapping(flowId);
409
- const direction = getDirectionFromBusinessType(businessType);
410
- const entity = options.entity;
411
- if (!['user', 'org', 'role'].includes(entity)) {
412
- throw new Error(`无效的实体类型: ${entity},可选值: user | org | role`);
413
- }
414
- const profileData = await (0, mapping_1.fetchProfileData)(flowId, refType);
415
- const subParams = getSubParams(profileData, entity, direction);
416
- const beforeLen = subParams.length;
417
- const newSubParams = subParams.filter((item) => direction === 'upstream' ? item.name !== options.name : item.value !== options.name);
418
- if (newSubParams.length === beforeLen) {
419
- throw new Error(`未找到映射: ${options.name}`);
420
- }
421
- // 写回过滤后的数组
422
- const [mappingKey, directionKey] = getMappingSubPath(entity, direction);
423
- const mapping = profileData[mappingKey];
424
- const dirData = mapping?.[directionKey];
425
- if (dirData) {
426
- dirData.sub_params = newSubParams;
427
- }
428
- await (0, mapping_1.editMapping)(flowId, refType, profileData);
429
- if (options.json) {
430
- (0, output_1.printJson)({ ok: true, message: '映射已删除', name: options.name, flowId });
431
- }
432
- else {
433
- (0, output_1.printSuccess)(`映射已删除: ${options.name}`);
434
- }
687
+ .action(wrapAction('删除映射')(async (flowId, options) => {
688
+ const entity = options.entity;
689
+ validateEntity(entity);
690
+ const businessType = await validateFlowSupportsMapping(flowId);
691
+ const direction = getDirectionFromBusinessType(businessType);
692
+ const refType = resolveRefType(options.type, businessType);
693
+ const profileData = await (0, mapping_1.fetchProfileData)(flowId, refType);
694
+ const subParams = getSubParams(profileData, entity, direction);
695
+ const beforeLen = subParams.length;
696
+ const newSubParams = subParams.filter((item) => direction === 'upstream' ? item.name !== options.name : item.value !== options.name);
697
+ if (newSubParams.length === beforeLen) {
698
+ throw new Error(`未找到映射: ${options.name}`);
435
699
  }
436
- catch (error) {
437
- if (options.json) {
438
- (0, output_1.printStructuredResult)({ ok: false, message: error.message });
439
- }
440
- else {
441
- (0, output_1.printError)(`删除映射失败: ${error.message}`);
442
- }
700
+ const [mappingKey, directionKey] = getMappingSubPath(entity, direction);
701
+ const mapping = profileData[mappingKey];
702
+ const dirData = mapping?.[directionKey];
703
+ if (dirData) {
704
+ dirData.sub_params = newSubParams;
443
705
  }
444
- });
706
+ await (0, mapping_1.editMapping)(flowId, refType, profileData);
707
+ if (options.json) {
708
+ (0, output_1.printJson)({ ok: true, message: '映射已删除', name: options.name, flowId });
709
+ }
710
+ else {
711
+ (0, output_1.printSuccess)(`映射已删除: ${options.name}`);
712
+ }
713
+ }));
445
714
  // ── check ───────────────────────────────────────────────
446
715
  mappingCmd
447
716
  .command('check <flowId>')
448
717
  .description('检查映射是否已配置')
449
718
  .option('--json', '以 JSON 格式输出')
450
- .action(async (flowId, options) => {
451
- try {
452
- if (options.json)
453
- (0, output_1.setJsonMode)(true);
454
- await validateFlowSupportsMapping(flowId);
455
- const result = await (0, mapping_1.checkMappingStatus)(flowId);
456
- if (options.json) {
457
- (0, output_1.printJson)({ ok: true, configured: result, flowId });
458
- return;
459
- }
460
- if (result) {
461
- (0, output_1.printSuccess)(`Flow ${flowId}: 映射已配置`);
462
- }
463
- else {
464
- (0, output_1.printWarning)(`Flow ${flowId}: 映射未配置`);
465
- }
719
+ .action(wrapAction('检查映射状态')(async (flowId, options) => {
720
+ await validateFlowSupportsMapping(flowId);
721
+ const result = await (0, mapping_1.checkMappingStatus)(flowId);
722
+ if (options.json) {
723
+ (0, output_1.printJson)({ ok: true, configured: result, flowId });
724
+ return;
466
725
  }
467
- catch (error) {
468
- if (options.json) {
469
- (0, output_1.printStructuredResult)({ ok: false, message: error.message });
470
- }
471
- else {
472
- (0, output_1.printError)(`检查映射状态失败: ${error.message}`);
473
- }
726
+ if (result) {
727
+ (0, output_1.printSuccess)(`Flow ${flowId}: 映射已配置`);
474
728
  }
475
- });
729
+ else {
730
+ (0, output_1.printWarning)(`Flow ${flowId}: 映射未配置`);
731
+ }
732
+ }));
476
733
  }
477
734
  //# sourceMappingURL=mapping.js.map