echoapi-converter 0.0.89 → 1.0.1

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.
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ var generate__default = /*#__PURE__*/_interopDefaultLegacy(generate);
24
24
  var JSON5__default = /*#__PURE__*/_interopDefaultLegacy(JSON5);
25
25
  var toJsonSchemasecond__default = /*#__PURE__*/_interopDefaultLegacy(toJsonSchemasecond);
26
26
 
27
- const DEFAULT_FIELD_TYPE$3 = [
27
+ const DEFAULT_FIELD_TYPE$4 = [
28
28
  "array",
29
29
  "boolean",
30
30
  "date",
@@ -194,18 +194,18 @@ const DEFAULT_BODY = {
194
194
  binary: {},
195
195
  };
196
196
  const DEFAULT_DEVELOP_ENUM = [
197
- "designing",
198
- "developing",
199
- "integrating",
200
- "testing",
197
+ "designing", // 设计中
198
+ "developing", // 开发中
199
+ "integrating", // 联调中
200
+ "testing", // 测试中
201
201
  ];
202
- const DEFAULT_COMPLETE_ENUM = ["tested", "released"];
202
+ const DEFAULT_COMPLETE_ENUM = ["tested", "released"]; // 已测完 已发布
203
203
  const DEFAULT_EDIT_ENUM = [
204
- "pending",
205
- "deprecated",
206
- "exception",
204
+ "pending", // 待确定
205
+ "deprecated", // 将废弃
206
+ "exception", // 有异常
207
207
  ];
208
- const DEFAULT_DISCARD_ENUM = ["obsolete"];
208
+ const DEFAULT_DISCARD_ENUM = ["obsolete"]; // 已废弃
209
209
  const DEFAULT_CONTENT_TYPE = ["json", "xml", "html", "binary"];
210
210
  const VARS_TYPE_MAP = {
211
211
  local: "variables",
@@ -618,7 +618,10 @@ const getSubstring = (str, length) => {
618
618
  }
619
619
  return str;
620
620
  };
621
- const hexSnowflake = (input) => {
621
+ const hexSnowflake = (input, unrelated) => {
622
+ if (unrelated) {
623
+ return apipostTools.snowflakeId();
624
+ }
622
625
  // 将输入转换为BigInt
623
626
  let n;
624
627
  if (typeof input === 'number') {
@@ -654,7 +657,7 @@ const hexSnowflake = (input) => {
654
657
  // 生成一个56bit范围内的数(确保14位16进制)
655
658
  const hashed = (n * 0x9e3779b97f4a7c15n) & ((1n << 56n) - 1n);
656
659
  // 转成hex并固定为14位长度
657
- return hashed.toString(16).padStart(14, '0');
660
+ return hashed.toString(16);
658
661
  };
659
662
  const parseConditionString = (str) => {
660
663
  // 定义所有可能的操作符枚举
@@ -1003,7 +1006,7 @@ const transFieldType = (str) => {
1003
1006
  const getFidldType = (type) => {
1004
1007
  if (!type)
1005
1008
  return 'String';
1006
- if (DEFAULT_FIELD_TYPE$3.includes(type?.toLowerCase())) {
1009
+ if (DEFAULT_FIELD_TYPE$4.includes(type?.toLowerCase())) {
1007
1010
  return transFieldType(type);
1008
1011
  }
1009
1012
  return 'String';
@@ -1019,7 +1022,7 @@ const getExampleId = (status) => {
1019
1022
  return apipostTools.snowflakeId();
1020
1023
  }
1021
1024
  };
1022
- const completionParameter = (parameter) => {
1025
+ const completionParameter$1 = (parameter) => {
1023
1026
  if (lodash.isArray(parameter)) {
1024
1027
  return parameter.map((p) => {
1025
1028
  const param = {
@@ -1140,16 +1143,16 @@ const completionRequestParam = (swaggerApi) => {
1140
1143
  const parameters = lodash.isArray(swaggerApi?.parameters) ? swaggerApi.parameters : [];
1141
1144
  return {
1142
1145
  header: {
1143
- parameter: completionParameter(parameters.filter(p => p?.in === 'header' && p?.name)),
1146
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'header' && p?.name)),
1144
1147
  },
1145
1148
  query: {
1146
- parameter: completionParameter(parameters.filter(p => p?.in === 'query' && p?.name)),
1149
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'query' && p?.name)),
1147
1150
  },
1148
1151
  restful: {
1149
- parameter: completionParameter(parameters.filter(p => p?.in === 'path' && p?.name)),
1152
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'path' && p?.name)),
1150
1153
  },
1151
1154
  cookie: {
1152
- parameter: completionParameter(parameters.filter(p => p?.in === 'cookie' && p?.name)),
1155
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'cookie' && p?.name)),
1153
1156
  },
1154
1157
  body: {
1155
1158
  ...completionBody(swaggerApi),
@@ -1428,13 +1431,13 @@ const completionWs2Request = (swaggerApi) => {
1428
1431
  const parameters = lodash.isArray(swaggerApi?.parameters) ? swaggerApi.parameters : [];
1429
1432
  return {
1430
1433
  header: {
1431
- parameter: completionParameter(parameters.filter(p => p?.in === 'header' && p?.name)),
1434
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'header' && p?.name)),
1432
1435
  },
1433
1436
  query: {
1434
- parameter: completionParameter(parameters.filter(p => p?.in === 'query' && p?.name)),
1437
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'query' && p?.name)),
1435
1438
  },
1436
1439
  cookie: {
1437
- parameter: completionParameter(parameters.filter(p => p?.in === 'cookie' && p?.name)),
1440
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'cookie' && p?.name)),
1438
1441
  },
1439
1442
  };
1440
1443
  };
@@ -1465,13 +1468,13 @@ const completionSocketIoRequest = (swaggerApi) => {
1465
1468
  const parameters = lodash.isArray(swaggerApi?.parameters) ? swaggerApi.parameters : [];
1466
1469
  return {
1467
1470
  header: {
1468
- parameter: completionParameter(parameters.filter(p => p?.in === 'header' && p?.name)),
1471
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'header' && p?.name)),
1469
1472
  },
1470
1473
  query: {
1471
- parameter: completionParameter(parameters.filter(p => p?.in === 'query' && p?.name)),
1474
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'query' && p?.name)),
1472
1475
  },
1473
1476
  cookie: {
1474
- parameter: completionParameter(parameters.filter(p => p?.in === 'cookie' && p?.name)),
1477
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'cookie' && p?.name)),
1475
1478
  },
1476
1479
  event: {
1477
1480
  parameter: lodash.isArray(parameters)
@@ -1514,10 +1517,10 @@ const completionGraphqlRequest = (swaggerApi) => {
1514
1517
  const parameters = lodash.isArray(swaggerApi?.parameters) ? swaggerApi.parameters : [];
1515
1518
  return {
1516
1519
  header: {
1517
- parameter: completionParameter(parameters.filter(p => p?.in === 'header' && p?.name)),
1520
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'header' && p?.name)),
1518
1521
  },
1519
1522
  cookie: {
1520
- parameter: completionParameter(parameters.filter(p => p?.in === 'cookie' && p?.name)),
1523
+ parameter: completionParameter$1(parameters.filter(p => p?.in === 'cookie' && p?.name)),
1521
1524
  },
1522
1525
  pre_tasks: [],
1523
1526
  post_tasks: [],
@@ -2167,7 +2170,7 @@ const t = (key, data) => {
2167
2170
  // @ts-nocheck
2168
2171
  const MAX_DEEP_COUNT = 10;
2169
2172
  const schemaPath = (name, version) => {
2170
- if (version === '2.0') {
2173
+ if (version === "2.0") {
2171
2174
  return `#/definitions/${name}`;
2172
2175
  }
2173
2176
  return `#/components/schemas/${name}`;
@@ -2176,18 +2179,19 @@ const deepModelRef = (originSchema, schemaMap, startSchema, count = 0) => {
2176
2179
  try {
2177
2180
  let deepCount = lodash.cloneDeep(count);
2178
2181
  const schema = lodash.cloneDeep(originSchema);
2179
- if (lodash.has(schema, 'x-schema-refs')) {
2180
- const refsValue = schema?.['x-schema-refs'];
2182
+ if (lodash.has(schema, "x-schema-refs")) {
2183
+ const refsValue = schema?.["x-schema-refs"];
2181
2184
  if (!lodash.isEmpty(refsValue) &&
2182
- Object.prototype.toString.call(schema?.properties) === '[object Object]') {
2183
- const properties = Object.prototype.toString.call(schema?.properties) === '[object Object]'
2185
+ Object.prototype.toString.call(schema?.properties) === "[object Object]") {
2186
+ const properties = Object.prototype.toString.call(schema?.properties) ===
2187
+ "[object Object]"
2184
2188
  ? schema?.properties
2185
2189
  : {};
2186
- schema['properties'] = lodash.values(refsValue)?.reduce((pre, item) => {
2187
- let refId = '';
2190
+ schema["properties"] = lodash.values(refsValue)?.reduce((pre, item) => {
2191
+ let refId = "";
2188
2192
  let refPath = item?.$ref;
2189
2193
  if (lodash.isString(refPath)) {
2190
- refId = refPath.split('/').pop() || '';
2194
+ refId = refPath.split("/").pop() || "";
2191
2195
  }
2192
2196
  if (refId &&
2193
2197
  lodash.has(schemaMap, refId) &&
@@ -2199,7 +2203,7 @@ const deepModelRef = (originSchema, schemaMap, startSchema, count = 0) => {
2199
2203
  // $ref: mapValue?.path,
2200
2204
  // };
2201
2205
  let mapSchema = mapValue?.schema;
2202
- if (lodash.has(mapValue?.schema, 'x-schema-refs')) {
2206
+ if (lodash.has(mapValue?.schema, "x-schema-refs")) {
2203
2207
  if (deepCount > MAX_DEEP_COUNT) {
2204
2208
  mapSchema = mapValue?.schema;
2205
2209
  }
@@ -2230,17 +2234,17 @@ const deepModelRef = (originSchema, schemaMap, startSchema, count = 0) => {
2230
2234
  }, properties);
2231
2235
  }
2232
2236
  }
2233
- if (lodash.has(schema, 'properties') &&
2234
- Object.prototype.toString.call(schema?.properties) === '[object Object]') {
2237
+ if (lodash.has(schema, "properties") &&
2238
+ Object.prototype.toString.call(schema?.properties) === "[object Object]") {
2235
2239
  let properties_keys = lodash.keys(schema?.properties);
2236
2240
  if (
2237
2241
  // 优化展示顺序
2238
- schema?.['x-schema-orders'] &&
2239
- lodash.isArray(schema?.['x-schema-orders']) &&
2240
- lodash.isEqual(lodash.sortBy(schema?.['x-schema-orders']), lodash.sortBy(lodash.keys(schema?.properties)))) {
2241
- properties_keys = schema?.['x-schema-orders'];
2242
+ schema?.["x-schema-orders"] &&
2243
+ lodash.isArray(schema?.["x-schema-orders"]) &&
2244
+ lodash.isEqual(lodash.sortBy(schema?.["x-schema-orders"]), lodash.sortBy(lodash.keys(schema?.properties)))) {
2245
+ properties_keys = schema?.["x-schema-orders"];
2242
2246
  }
2243
- schema['properties'] = properties_keys?.reduce((pre, key) => {
2247
+ schema["properties"] = properties_keys?.reduce((pre, key) => {
2244
2248
  if (key && !lodash.isEmpty(schema?.properties[key])) {
2245
2249
  if (deepCount > MAX_DEEP_COUNT) {
2246
2250
  pre[key] = schema?.properties[key];
@@ -2254,30 +2258,35 @@ const deepModelRef = (originSchema, schemaMap, startSchema, count = 0) => {
2254
2258
  }
2255
2259
  if (lodash.isString(schema?.$ref) && schema.$ref.length > 0) {
2256
2260
  let refPath = schema?.$ref;
2257
- const parts = refPath.split('/');
2261
+ const parts = refPath.split("/");
2258
2262
  if (parts.length > 0) {
2259
- let refId = parts[parts.length - 1] || '';
2263
+ let refId = parts[parts.length - 1] || "";
2260
2264
  if (lodash.has(schemaMap, refId)) {
2261
2265
  parts[parts.length - 1] = schemaMap[refId]?.name || refId; // 替换最后一部分
2262
- schema.$ref = parts.join('/');
2266
+ schema.$ref = parts.join("/");
2263
2267
  }
2264
2268
  }
2265
2269
  }
2266
2270
  // 特殊处理properties为数组的情况
2267
- if (lodash.has(schema, 'properties') && Object.prototype.toString.call(schema?.properties) !== '[object Object]') {
2271
+ if (lodash.has(schema, "properties") &&
2272
+ Object.prototype.toString.call(schema?.properties) !== "[object Object]") {
2268
2273
  schema.properties = {};
2269
2274
  }
2270
- if (schema?.type === 'array' && lodash.has(schema, 'items')) {
2271
- if (lodash.has(schema?.items, 'properties') &&
2272
- Object.prototype.toString.call(schema?.items?.properties) === '[object Object]') {
2275
+ if (schema?.type === "array" && lodash.has(schema, "items")) {
2276
+ if (lodash.has(schema?.items, "properties") &&
2277
+ Object.prototype.toString.call(schema?.items?.properties) ===
2278
+ "[object Object]") {
2273
2279
  if (deepCount <= MAX_DEEP_COUNT) {
2274
2280
  schema.items = deepModelRef(schema?.items, schemaMap, startSchema || originSchema, ++deepCount);
2275
2281
  }
2276
2282
  }
2283
+ else if (lodash.has(schema?.items, "$ref")) {
2284
+ schema.items = deepModelRef(schema?.items, schemaMap, startSchema || originSchema, deepCount);
2285
+ }
2277
2286
  }
2278
2287
  // 处理数组的引用
2279
- delete schema?.['x-schema-orders'];
2280
- delete schema?.['x-schema-refs'];
2288
+ delete schema?.["x-schema-orders"];
2289
+ delete schema?.["x-schema-refs"];
2281
2290
  return schema;
2282
2291
  }
2283
2292
  catch (err) {
@@ -2406,10 +2415,10 @@ const handlePathItemParameters = (type, arr, pathItem) => {
2406
2415
  example: String(item?.value || ""),
2407
2416
  schema: {
2408
2417
  type: item?.field_type?.toLowerCase(),
2409
- ...(item?.schema || {})
2418
+ ...(item?.schema || {}),
2410
2419
  },
2411
2420
  };
2412
- const oldFiledObj = OLD_FIELD_TYPES?.[param?.schema?.type || ''];
2421
+ const oldFiledObj = OLD_FIELD_TYPES?.[param?.schema?.type || ""];
2413
2422
  if (oldFiledObj) {
2414
2423
  param.field_type = oldFiledObj.type;
2415
2424
  param.schema.type = oldFiledObj.type;
@@ -2441,7 +2450,7 @@ const handlePathItemBodyParameters = (body, pathItem, modelsObj) => {
2441
2450
  name: "body",
2442
2451
  description: "",
2443
2452
  schema: deepModelRef(body?.raw_schema || {
2444
- type: 'object'
2453
+ type: "object",
2445
2454
  }, modelsObj),
2446
2455
  type: "string",
2447
2456
  example: body?.raw || "",
@@ -2474,22 +2483,22 @@ const handleGraphqlRequestBody = (query_list, query_schema, pathItem, modelsObj)
2474
2483
  if (!lodash.has(pathItem, "requestBody")) {
2475
2484
  pathItem.requestBody = {
2476
2485
  content: {},
2477
- 'x-schema': query_schema || {}
2486
+ "x-schema": query_schema || {},
2478
2487
  };
2479
2488
  }
2480
- query_list.forEach(m => {
2489
+ query_list.forEach((m) => {
2481
2490
  const mode = `x-${m?.param_id}`;
2482
2491
  pathItem.requestBody.content[mode] = {
2483
- 'x-query': m?.query || '',
2484
- 'x-variables': m?.variables || '',
2485
- 'x-summary': m?.name || '',
2486
- 'x-response': {
2487
- 'x-mode': m?.response?.mode || '',
2492
+ "x-query": m?.query || "",
2493
+ "x-variables": m?.variables || "",
2494
+ "x-summary": m?.name || "",
2495
+ "x-response": {
2496
+ "x-mode": m?.response?.mode || "",
2488
2497
  example: m?.response?.raw || "",
2489
2498
  schema: deepModelRef(m?.response?.raw_schema || {
2490
2499
  type: "object",
2491
2500
  }, modelsObj),
2492
- }
2501
+ },
2493
2502
  };
2494
2503
  });
2495
2504
  }
@@ -2497,16 +2506,22 @@ const handleGraphqlRequestBody = (query_list, query_schema, pathItem, modelsObj)
2497
2506
  const handleSocketMethodParameterDescription = (item, mode) => {
2498
2507
  let description = item?.description;
2499
2508
  let rules = item?.rules;
2500
- if (mode == 'fixed_message') {
2501
- return `${description}\n${t('tcpMethodMessage', {
2502
- direction: rules?.fill_type == 'left' ? t('left') : rules?.fill_type == 'right' ? t('right') : '',
2509
+ if (mode == "fixed_message") {
2510
+ return `${description}\n${t("tcpMethodMessage", {
2511
+ direction: rules?.fill_type == "left"
2512
+ ? t("left")
2513
+ : rules?.fill_type == "right"
2514
+ ? t("right")
2515
+ : "",
2503
2516
  size: rules?.length,
2504
- str: rules?.content_type == 'common' ? RULE_TYPES[rules?.common] : rules?.custom
2517
+ str: rules?.content_type == "common"
2518
+ ? RULE_TYPES[rules?.common]
2519
+ : rules?.custom,
2505
2520
  })}`;
2506
2521
  }
2507
- else if (mode == 'delimiter_message') {
2508
- return `${description}\n${t('tcpMethodDelimiterMessage', {
2509
- str: RULE_TYPES_ICON[rules?.delimiter]
2522
+ else if (mode == "delimiter_message") {
2523
+ return `${description}\n${t("tcpMethodDelimiterMessage", {
2524
+ str: RULE_TYPES_ICON[rules?.delimiter],
2510
2525
  })}`;
2511
2526
  }
2512
2527
  return description;
@@ -2520,9 +2535,9 @@ const handleSocketMethodRequestBody = (body, pathItem) => {
2520
2535
  }
2521
2536
  const mode = MODE_TYPE[body?.mode];
2522
2537
  const parameter = body?.parameter || [];
2523
- if (['delimiter_message', 'fixed_message'].includes(body?.mode)) {
2538
+ if (["delimiter_message", "fixed_message"].includes(body?.mode)) {
2524
2539
  pathItem.requestBody.content[body?.mode] = {
2525
- 'x-mode': body?.mode || '',
2540
+ "x-mode": body?.mode || "",
2526
2541
  schema: {
2527
2542
  type: "object",
2528
2543
  properties: parameter.reduce((lastData, item) => {
@@ -2544,10 +2559,12 @@ const handleSocketMethodRequestBody = (body, pathItem) => {
2544
2559
  else {
2545
2560
  if (mode) {
2546
2561
  pathItem.requestBody.content[mode] = {
2547
- 'x-mode': mode || '',
2548
- schema: lodash.isPlainObject(body?.raw_schema) && !lodash.isEmpty(body?.raw_schema) ? body?.raw_schema : {
2549
- type: "object",
2550
- },
2562
+ "x-mode": mode || "",
2563
+ schema: lodash.isPlainObject(body?.raw_schema) && !lodash.isEmpty(body?.raw_schema)
2564
+ ? body?.raw_schema
2565
+ : {
2566
+ type: "object",
2567
+ },
2551
2568
  example: body?.raw || "",
2552
2569
  };
2553
2570
  }
@@ -2561,22 +2578,22 @@ const handleMessagePathItemrequestBody = (message, pathItem, modelsObj) => {
2561
2578
  content: {},
2562
2579
  };
2563
2580
  }
2564
- message.forEach(m => {
2581
+ message.forEach((m) => {
2565
2582
  const mode = `x-${m?.param_id}`;
2566
2583
  pathItem.requestBody.content[mode] = {
2567
- 'x-mode': m?.request?.mode || '',
2568
- 'x-summary': m?.name || '',
2584
+ "x-mode": m?.request?.mode || "",
2585
+ "x-summary": m?.name || "",
2569
2586
  schema: deepModelRef(m?.request?.raw_schema || {
2570
2587
  type: "object",
2571
2588
  }, modelsObj),
2572
2589
  example: m?.request?.raw || "",
2573
- 'x-response': {
2574
- 'x-mode': m?.response?.mode || '',
2590
+ "x-response": {
2591
+ "x-mode": m?.response?.mode || "",
2575
2592
  example: m?.response?.raw || "",
2576
2593
  schema: deepModelRef(m?.response?.raw_schema || {
2577
2594
  type: "object",
2578
2595
  }, modelsObj),
2579
- }
2596
+ },
2580
2597
  };
2581
2598
  });
2582
2599
  }
@@ -2593,7 +2610,7 @@ const handlePathItemResponse = (response, modelsObj) => {
2593
2610
  content: {
2594
2611
  [MODE_TYPE?.[expect?.content_type] || "*/*"]: {
2595
2612
  schema: deepModelRef(expect?.schema || {}, modelsObj),
2596
- example: raw || '',
2613
+ example: raw || "",
2597
2614
  },
2598
2615
  },
2599
2616
  };
@@ -2636,20 +2653,21 @@ const handlePathItemRequestBody = (body, pathItem, modelsObj) => {
2636
2653
  item.key.length > 0 &&
2637
2654
  (!lodash.has(item, "is_checked") || item?.is_checked > 0)) {
2638
2655
  lastData[item.key] = {
2639
- type: item?.field_type?.toLowerCase() || 'string',
2656
+ type: item?.field_type?.toLowerCase() || "string",
2640
2657
  description: item?.description || "",
2641
2658
  example: item?.value || "",
2642
- ...(lodash.isPlainObject(item?.schema) ? item.schema : {})
2659
+ ...(lodash.isPlainObject(item?.schema) ? item.schema : {}),
2643
2660
  };
2644
2661
  }
2645
2662
  return lastData;
2646
2663
  }, {}),
2647
2664
  required: parameter.reduce((lastArr, item) => {
2648
- if (lodash.isEqual(item?.not_null, 1) && !lodash.includes(lastArr, item.key)) {
2665
+ if (lodash.isEqual(item?.not_null, 1) &&
2666
+ !lodash.includes(lastArr, item.key)) {
2649
2667
  lastArr.push(item.key);
2650
2668
  }
2651
2669
  return lastArr;
2652
- }, [])
2670
+ }, []),
2653
2671
  },
2654
2672
  };
2655
2673
  }
@@ -2667,39 +2685,40 @@ const getUserShowName = (data) => {
2667
2685
  if (lodash.isString(data?.nick_name) && data?.nick_name.length > 0) {
2668
2686
  return data?.nick_name;
2669
2687
  }
2670
- return '';
2688
+ return "";
2671
2689
  };
2672
2690
  const createPathItem = (item, sourceObj, pid, pidName, modelsObj, apiVersion, target_type) => {
2673
2691
  const path = recursiveFolderPath("", sourceObj, pid, pidName);
2674
2692
  const pathItem = {
2675
- 'x-target-id': item?.target_id || '',
2676
- 'x-protocol': target_type || '',
2693
+ "x-target-id": item?.target_id || "",
2694
+ "x-protocol": target_type || "",
2695
+ "x-sort": item?.sort || 0,
2677
2696
  summary: item?.name || "",
2678
2697
  description: item?.description || "",
2679
- tags: []
2698
+ tags: [],
2680
2699
  };
2681
- if (lodash.has(item, 'mock_server_enable')) {
2682
- pathItem['x-mock-server-enable'] = item?.mock_server_enable;
2700
+ if (lodash.has(item, "mock_server_enable")) {
2701
+ pathItem["x-mock-server-enable"] = item?.mock_server_enable;
2683
2702
  }
2684
2703
  if (lodash.isArray(item?.tags) && item?.tags.length > 0) {
2685
- pathItem['x-tags'] = item?.tags;
2704
+ pathItem["x-tags"] = item?.tags;
2686
2705
  }
2687
2706
  if (lodash.isString(item?.mark_id)) {
2688
- pathItem['x-mark-id'] = item?.mark_id;
2707
+ pathItem["x-mark-id"] = item?.mark_id;
2689
2708
  }
2690
2709
  if (lodash.isString(item?.updated_at)) {
2691
- pathItem['x-updated-at'] = item?.updated_at;
2710
+ pathItem["x-updated-at"] = item?.updated_at;
2692
2711
  }
2693
2712
  if (lodash.isString(item?.updated_user?.nick_name)) {
2694
- pathItem['x-updated-user-name'] = getUserShowName(item?.updated_user);
2713
+ pathItem["x-updated-user-name"] = getUserShowName(item?.updated_user);
2695
2714
  }
2696
2715
  if (lodash.isPlainObject(item?.attribute_info) && !lodash.isEmpty(item?.attribute_info)) {
2697
- pathItem['x-attribute-info'] = item?.attribute_info;
2716
+ pathItem["x-attribute-info"] = item?.attribute_info;
2698
2717
  }
2699
2718
  if (item?.is_exampled === 1) {
2700
- pathItem['x-exampled'] = item?.is_exampled;
2719
+ pathItem["x-exampled"] = item?.is_exampled;
2701
2720
  }
2702
- if (['http', 'sse'].includes(target_type)) {
2721
+ if (["http", "sse"].includes(target_type)) {
2703
2722
  // 处理 Query 和 Header 参数
2704
2723
  handlePathItemParameters("query", item?.request?.query?.parameter || [], pathItem);
2705
2724
  handlePathItemParameters("header", item?.request?.header?.parameter || [], pathItem);
@@ -2720,27 +2739,37 @@ const createPathItem = (item, sourceObj, pid, pidName, modelsObj, apiVersion, ta
2720
2739
  // 处理响应
2721
2740
  pathItem.responses = handlePathItemResponse(item?.response || {}, modelsObj);
2722
2741
  }
2723
- else if (['websocket2', 'socketio', 'graphql'].includes(target_type)) {
2742
+ else if (["websocket2", "socketio", "graphql"].includes(target_type)) {
2724
2743
  // 拼接description
2725
2744
  if (lodash.isPlainObject(item?.config)) {
2726
2745
  switch (target_type) {
2727
- case 'socketio':
2746
+ case "socketio":
2728
2747
  pathItem.description = `${pathItem.description}
2729
- ${item?.config?.shake_hands_path ? t('securityConnectionMessage', {
2730
- enable: item?.config?.certificate_verification == -1 ? t('notNeedEnable') : t('needEnable'),
2731
- version: item?.config?.socket_version || 'v4',
2732
- path: item?.config?.shake_hands_path
2733
- }) : t('securityConnectionMessageNoPath', {
2734
- enable: item?.config?.certificate_verification == -1 ? t('notNeedEnable') : t('needEnable'),
2735
- version: item?.config?.socket_version || 'v4',
2736
- })}
2748
+ ${item?.config?.shake_hands_path
2749
+ ? t("securityConnectionMessage", {
2750
+ enable: item?.config?.certificate_verification == -1
2751
+ ? t("notNeedEnable")
2752
+ : t("needEnable"),
2753
+ version: item?.config?.socket_version || "v4",
2754
+ path: item?.config?.shake_hands_path,
2755
+ })
2756
+ : t("securityConnectionMessageNoPath", {
2757
+ enable: item?.config?.certificate_verification == -1
2758
+ ? t("notNeedEnable")
2759
+ : t("needEnable"),
2760
+ version: item?.config?.socket_version || "v4",
2761
+ })}
2737
2762
  `;
2738
2763
  break;
2739
- case 'websocket2':
2764
+ case "websocket2":
2740
2765
  pathItem.description = `${pathItem.description}
2741
- ${t('wsConfigMessage', {
2742
- enable: item?.config?.certificate_verification == -1 ? t('notNeedEnable') : t('needEnable'),
2743
- content: !item?.config?.information_size || item?.config?.information_size == 0 ? t('unlimited') : `${item?.config?.information_size}M`
2766
+ ${t("wsConfigMessage", {
2767
+ enable: item?.config?.certificate_verification == -1
2768
+ ? t("notNeedEnable")
2769
+ : t("needEnable"),
2770
+ content: !item?.config?.information_size || item?.config?.information_size == 0
2771
+ ? t("unlimited")
2772
+ : `${item?.config?.information_size}M`,
2744
2773
  })}
2745
2774
  `;
2746
2775
  break;
@@ -2750,10 +2779,10 @@ ${t('wsConfigMessage', {
2750
2779
  handlePathItemParameters("header", item?.request?.header?.parameter || [], pathItem);
2751
2780
  handlePathItemParameters("cookie", item?.request?.cookie?.parameter || [], pathItem);
2752
2781
  handlePathItemParameters("path", item?.request?.restful?.parameter || [], pathItem);
2753
- if (target_type == 'socketio')
2782
+ if (target_type == "socketio")
2754
2783
  handlePathItemParameters("event", item?.request?.event?.parameter || [], pathItem);
2755
2784
  // 处理请体
2756
- if (target_type == 'graphql') {
2785
+ if (target_type == "graphql") {
2757
2786
  handleGraphqlRequestBody(item?.request?.body?.query_list || [], item?.request?.body?.query_schema || {}, pathItem, modelsObj);
2758
2787
  }
2759
2788
  else {
@@ -2764,22 +2793,24 @@ ${t('wsConfigMessage', {
2764
2793
  pathItem.tags = [...pathItem.tags, path];
2765
2794
  }
2766
2795
  }
2767
- else if (target_type == 'socket_method') {
2796
+ else if (target_type == "socket_method") {
2768
2797
  // 拼接description
2769
2798
  const configs = item?.request?.configs;
2770
2799
  if (lodash.isPlainObject(configs)) {
2771
- let requestString = `${t('requestEncodingFormat', { format: configs?.charset })} ${lodash.isArray(configs?.func?.request) && configs?.func?.request.length > 0 ?
2772
- `\n${t('needAddRequestDataHandleFunction')}\n${configs?.func?.request.map((r, index) => {
2800
+ let requestString = `${t("requestEncodingFormat", {
2801
+ format: configs?.charset,
2802
+ })} ${lodash.isArray(configs?.func?.request) && configs?.func?.request.length > 0
2803
+ ? `\n${t("needAddRequestDataHandleFunction")}\n${configs?.func?.request.map((r, index) => {
2773
2804
  let str = getTcpMethodFucString(r);
2774
2805
  return str;
2775
2806
  })}`
2776
- : ''}`;
2777
- let responseString = lodash.isArray(configs?.func?.response) && configs?.func?.response.length > 0 ?
2778
- `${t('needAddResponseDataHandleFunction')}\n${configs?.func?.response.map((r, index) => {
2807
+ : ""}`;
2808
+ let responseString = lodash.isArray(configs?.func?.response) && configs?.func?.response.length > 0
2809
+ ? `${t("needAddResponseDataHandleFunction")}\n${configs?.func?.response.map((r, index) => {
2779
2810
  let str = getTcpMethodFucString(r);
2780
2811
  return str;
2781
2812
  })}`
2782
- : '';
2813
+ : "";
2783
2814
  pathItem.description = `${pathItem.description}\n${requestString}\n${responseString}`;
2784
2815
  }
2785
2816
  handleSocketMethodRequestBody(item?.request?.body || {}, pathItem);
@@ -2790,7 +2821,7 @@ ${t('wsConfigMessage', {
2790
2821
  pathItem.tags = [...pathItem.tags, path];
2791
2822
  }
2792
2823
  }
2793
- else if (target_type == 'doc') {
2824
+ else if (target_type == "doc") {
2794
2825
  // 添加路径标签
2795
2826
  if (path?.length > 0 && !pathItem.tags.includes(path)) {
2796
2827
  pathItem.tags = [...pathItem.tags, path];
@@ -2800,33 +2831,47 @@ ${t('wsConfigMessage', {
2800
2831
  };
2801
2832
  const getTcpMethodFucString = (func) => {
2802
2833
  switch (func?.id) {
2803
- case 'addCharToPacketEnd':
2804
- return t('addNewline', { str: func?.option });
2805
- case 'calcLengthToPacketHeader':
2806
- return t('addContentLength', { size: func?.option });
2807
- case 'removePacketHeader':
2808
- return t('removeResponseHeader', { size: func?.option });
2809
- case 'removeWrapChar':
2810
- return t('trimTrailingNewline', { str: func?.option });
2811
- case 'parseXmlToJson':
2812
- return t('convertXmlToJson');
2813
- }
2814
- return '';
2834
+ case "addCharToPacketEnd":
2835
+ return t("addNewline", { str: func?.option });
2836
+ case "calcLengthToPacketHeader":
2837
+ return t("addContentLength", { size: func?.option });
2838
+ case "removePacketHeader":
2839
+ return t("removeResponseHeader", { size: func?.option });
2840
+ case "removeWrapChar":
2841
+ return t("trimTrailingNewline", { str: func?.option });
2842
+ case "parseXmlToJson":
2843
+ return t("convertXmlToJson");
2844
+ }
2845
+ return "";
2815
2846
  };
2816
2847
  const getSocketRequestStr = (end_func) => {
2817
2848
  switch (end_func?.name) {
2818
- case 'none':
2819
- return t('completeOnReceive');
2820
- case 'endedChar':
2821
- return t('specialCharText', { str: end_func?.option });
2822
- case 'endedHexChar':
2823
- return t('specialCharBinary', { str: end_func?.option });
2824
- case 'endedHeaderByteLength':
2825
- return t('headerBodyFormat', { size: end_func?.option });
2826
- case 'endedContentByteLength':
2827
- return t('fixedLength', { size: end_func?.option });
2828
- }
2829
- return '';
2849
+ case "none":
2850
+ return t("completeOnReceive");
2851
+ case "endedChar":
2852
+ return t("specialCharText", { str: end_func?.option });
2853
+ case "endedHexChar":
2854
+ return t("specialCharBinary", { str: end_func?.option });
2855
+ case "endedHeaderByteLength":
2856
+ return t("headerBodyFormat", { size: end_func?.option });
2857
+ case "endedContentByteLength":
2858
+ return t("fixedLength", { size: end_func?.option });
2859
+ }
2860
+ return "";
2861
+ };
2862
+ const stripExtensions = (obj) => {
2863
+ if (Array.isArray(obj))
2864
+ return obj.map(stripExtensions);
2865
+ if (obj && typeof obj === "object") {
2866
+ const result = {};
2867
+ for (const key of Object.keys(obj)) {
2868
+ if (!key.startsWith("x-")) {
2869
+ result[key] = stripExtensions(obj[key]);
2870
+ }
2871
+ }
2872
+ return result;
2873
+ }
2874
+ return obj;
2830
2875
  };
2831
2876
 
2832
2877
  // @ts-nocheck
@@ -2857,24 +2902,27 @@ class ApipostToSwagger {
2857
2902
  handleProject() {
2858
2903
  const { name, intro, marks, attributes, project_id } = this.apiToSwaggerOrigin.project || {};
2859
2904
  this.apiToSwaggerResult.info = {
2860
- title: name || t('createProj'),
2905
+ title: name || t("createProj"),
2861
2906
  description: intro || "",
2862
2907
  version: "1.0.0",
2863
2908
  };
2864
2909
  if (lodash.isString(project_id)) {
2865
- this.apiToSwaggerResult.info['x-project-id'] = project_id;
2910
+ this.apiToSwaggerResult.info["x-project-id"] = project_id;
2866
2911
  }
2867
2912
  if (this.apiToSwaggerVersion == "2.0") {
2868
2913
  this.apiToSwaggerResult.swagger = "2.0";
2869
2914
  }
2870
- else if (this.apiToSwaggerVersion == "3.0") {
2915
+ else if (this.apiToSwaggerVersion == "3.1") {
2916
+ this.apiToSwaggerResult.openapi = "3.1.0";
2917
+ }
2918
+ else {
2871
2919
  this.apiToSwaggerResult.openapi = "3.0.0";
2872
2920
  }
2873
2921
  if (lodash.isArray(marks) && marks.length > 0) {
2874
- this.apiToSwaggerResult.info['x-marks'] = marks;
2922
+ this.apiToSwaggerResult.info["x-marks"] = marks;
2875
2923
  }
2876
2924
  if (lodash.isArray(attributes) && attributes.length > 0) {
2877
- this.apiToSwaggerResult.info['x-attributes'] = attributes;
2925
+ this.apiToSwaggerResult.info["x-attributes"] = attributes;
2878
2926
  }
2879
2927
  }
2880
2928
  handleModels() {
@@ -2884,9 +2932,9 @@ class ApipostToSwagger {
2884
2932
  const schemaMap = childModels?.reduce((pre, item) => {
2885
2933
  if (item?.model_id && item?.name) {
2886
2934
  pre[item?.model_id] = {
2887
- schema: item?.schema || { type: 'object', properties: {} },
2935
+ schema: item?.schema || { type: "object", properties: {} },
2888
2936
  path: schemaPath(item?.name, version),
2889
- name: item?.name || '',
2937
+ name: item?.name || "",
2890
2938
  };
2891
2939
  }
2892
2940
  return pre;
@@ -2899,10 +2947,10 @@ class ApipostToSwagger {
2899
2947
  return pre;
2900
2948
  }, {});
2901
2949
  // 先不区分目录概念 把所有的schema都放在schemas目录下 后期加上schemas生成多目录
2902
- if (version === '2.0') {
2950
+ if (version === "2.0") {
2903
2951
  this.apiToSwaggerResult.definitions = schemas;
2904
2952
  }
2905
- if (lodash.isEqual(version, '3.0') || lodash.isEqual(version, '3.0.0')) {
2953
+ if (version === "3.1" || lodash.isEqual(version, "3.0") || lodash.isEqual(version, "3.0.0")) {
2906
2954
  this.apiToSwaggerResult.components = { schemas };
2907
2955
  }
2908
2956
  }
@@ -2915,9 +2963,9 @@ class ApipostToSwagger {
2915
2963
  for (const env of envs) {
2916
2964
  const servers = {
2917
2965
  url: env?.url || "",
2918
- description: env?.name || t('createEnv'),
2919
- "x-env-id": env?.env_id || '',
2920
- "x-selected": env?.is_selected
2966
+ description: env?.name || t("createEnv"),
2967
+ "x-env-id": env?.env_id || "",
2968
+ "x-selected": env?.is_selected,
2921
2969
  };
2922
2970
  if (lodash.isPlainObject(env?.env_var_list)) {
2923
2971
  servers.variables = {};
@@ -2998,17 +3046,18 @@ class ApipostToSwagger {
2998
3046
  if (!id || id == undefined) {
2999
3047
  continue;
3000
3048
  }
3001
- if (['sse', 'api'].includes(item.target_type)) {
3049
+ console.log(item.url, item.sort, "itemitem");
3050
+ if (["sse", "api"].includes(item.target_type)) {
3002
3051
  const temp_url = removeQuery(item?.url);
3003
3052
  const targetMethod = item?.method?.toLowerCase();
3004
- const pathItem = createPathItem(item, sourceObj, pid, pidName, modelsObj, this.apiToSwaggerVersion, item.target_type == 'api' ? 'http' : item.target_type);
3053
+ const pathItem = createPathItem(item, sourceObj, pid, pidName, modelsObj, this.apiToSwaggerVersion, item.target_type == "api" ? "http" : item.target_type);
3005
3054
  if (!paths[temp_url])
3006
3055
  paths[temp_url] = {};
3007
3056
  if (!paths[temp_url][targetMethod]) {
3008
3057
  paths[temp_url][targetMethod] = pathItem;
3009
3058
  }
3010
3059
  else if (pathItem.tags.length > 0) {
3011
- lodash.forEach(pathItem.tags, tag => {
3060
+ lodash.forEach(pathItem.tags, (tag) => {
3012
3061
  if (!paths[temp_url][targetMethod].tags.includes(tag)) {
3013
3062
  // 排除重复目录
3014
3063
  paths[temp_url][targetMethod].tags.push(tag);
@@ -3018,15 +3067,17 @@ class ApipostToSwagger {
3018
3067
  }
3019
3068
  else if (["folder", "socket"].includes(item.target_type)) {
3020
3069
  const path = recursiveFolderPath(`${item?.name}`, sourceObj, pid, pidName);
3070
+ console.log(path, "path-folder");
3021
3071
  item.path = path;
3022
- if (!lodash.has(folderObj, item?.name)) {
3072
+ if (!lodash.has(folderObj, item?.path)) {
3023
3073
  if (!this.apiToSwaggerResult.tags) {
3024
3074
  this.apiToSwaggerResult.tags = [];
3025
3075
  }
3026
3076
  // 收到数据即认为完成(不处理分包问题) none
3027
- if (item.target_type === 'socket' && lodash.isPlainObject(item?.request?.end_func)) {
3028
- if (!folderObj?.[item?.name]) {
3029
- item.description = `| ${t('serverAddress')} | ${t('pktCompletion')} |
3077
+ if (item.target_type === "socket" &&
3078
+ lodash.isPlainObject(item?.request?.end_func)) {
3079
+ if (!folderObj?.[item?.path]) {
3080
+ item.description = `| ${t("serverAddress")} | ${t("pktCompletion")} |
3030
3081
  | --- | --- |
3031
3082
  | ${item?.url} | ${getSocketRequestStr(item?.request?.end_func)}
3032
3083
  ${item.description}
@@ -3034,16 +3085,18 @@ class ApipostToSwagger {
3034
3085
  }
3035
3086
  }
3036
3087
  this.apiToSwaggerResult.tags.push({
3037
- name: item?.name || t('createDir'),
3088
+ name: item?.path || t("createDir"),
3038
3089
  description: item?.description || "",
3039
- 'x-type': item.target_type,
3040
- 'x-url': item?.url || '',
3041
- 'x-target-id': item?.target_id || ''
3090
+ "x-type": item.target_type,
3091
+ "x-url": item?.url || "",
3092
+ "x-target-id": item?.target_id || "",
3093
+ "x-sort": item?.sort || 0,
3094
+ "x-parent-id": item?.parent_id || "",
3042
3095
  });
3043
- folderObj[item?.name] = item;
3096
+ folderObj[item?.path] = item;
3044
3097
  }
3045
3098
  }
3046
- else if (['websocket2', 'socketio', 'graphql'].includes(item.target_type)) {
3099
+ else if (["websocket2", "socketio", "graphql"].includes(item.target_type)) {
3047
3100
  const temp_url = removeQuery(item?.url);
3048
3101
  const targetMethod = `x-${item?.target_id}`;
3049
3102
  const pathItem = createPathItem(item, sourceObj, pid, pidName, modelsObj, this.apiToSwaggerVersion, item.target_type);
@@ -3053,7 +3106,7 @@ class ApipostToSwagger {
3053
3106
  paths[temp_url][targetMethod] = pathItem;
3054
3107
  }
3055
3108
  else if (pathItem.tags.length > 0) {
3056
- lodash.forEach(pathItem.tags, tag => {
3109
+ lodash.forEach(pathItem.tags, (tag) => {
3057
3110
  if (!paths[temp_url][targetMethod].tags.includes(tag)) {
3058
3111
  // 排除重复目录
3059
3112
  paths[temp_url][targetMethod].tags.push(tag);
@@ -3061,8 +3114,10 @@ class ApipostToSwagger {
3061
3114
  });
3062
3115
  }
3063
3116
  }
3064
- else if (item.target_type === 'socket_method') {
3065
- const temp_url = sourceObj?.[pid] && sourceObj[pid]?.url ? sourceObj[pid]?.url : `${item?.name}`;
3117
+ else if (item.target_type === "socket_method") {
3118
+ const temp_url = sourceObj?.[pid] && sourceObj[pid]?.url
3119
+ ? sourceObj[pid]?.url
3120
+ : `${item?.name}`;
3066
3121
  const targetMethod = `x-${item.target_id}`;
3067
3122
  const pathItem = createPathItem(item, sourceObj, pid, pidName, modelsObj, this.apiToSwaggerVersion, item.target_type);
3068
3123
  if (!paths[temp_url])
@@ -3071,7 +3126,7 @@ class ApipostToSwagger {
3071
3126
  paths[temp_url][targetMethod] = pathItem;
3072
3127
  }
3073
3128
  else if (pathItem.tags.length > 0) {
3074
- lodash.forEach(pathItem.tags, tag => {
3129
+ lodash.forEach(pathItem.tags, (tag) => {
3075
3130
  if (!paths[temp_url][targetMethod].tags.includes(tag)) {
3076
3131
  // 排除重复目录
3077
3132
  paths[temp_url][targetMethod].tags.push(tag);
@@ -3079,7 +3134,7 @@ class ApipostToSwagger {
3079
3134
  });
3080
3135
  }
3081
3136
  }
3082
- else if (item.target_type === 'doc') {
3137
+ else if (item.target_type === "doc") {
3083
3138
  const temp_url = `x-${item.target_id}`;
3084
3139
  const targetMethod = `x-${item?.name}`;
3085
3140
  const pathItem = createPathItem(item, sourceObj, pid, pidName, modelsObj, this.apiToSwaggerVersion, item.target_type);
@@ -3089,7 +3144,7 @@ class ApipostToSwagger {
3089
3144
  paths[temp_url][targetMethod] = pathItem;
3090
3145
  }
3091
3146
  else if (pathItem.tags.length > 0) {
3092
- lodash.forEach(pathItem.tags, tag => {
3147
+ lodash.forEach(pathItem.tags, (tag) => {
3093
3148
  if (!paths[temp_url][targetMethod].tags.includes(tag)) {
3094
3149
  // 排除重复目录
3095
3150
  paths[temp_url][targetMethod].tags.push(tag);
@@ -3124,9 +3179,81 @@ class ApipostToSwagger {
3124
3179
  this.array2TreeExport("target_id", "parent_id", modelsObj) || [];
3125
3180
  }
3126
3181
  }
3127
- async apiToswagger(apipostObj, version, language) {
3182
+ sortApiNodes(nodes) {
3183
+ // 1. 构建 id -> node 的映射,并初始化 children
3184
+ const nodeMap = new Map();
3185
+ nodes.forEach((node) => {
3186
+ nodeMap.set(node["x-target-id"], { ...node, children: [] });
3187
+ });
3188
+ const roots = [];
3189
+ // 2. 建立父子关系
3190
+ nodes.forEach((node) => {
3191
+ const currentNode = nodeMap.get(node["x-target-id"]);
3192
+ const parentId = node["x-parent-id"];
3193
+ if (parentId === "0") {
3194
+ roots.push(currentNode);
3195
+ }
3196
+ else {
3197
+ const parent = nodeMap.get(parentId);
3198
+ if (parent) {
3199
+ parent.children.push(currentNode);
3200
+ }
3201
+ else {
3202
+ // 防御:若父节点不存在,当作根节点处理
3203
+ roots.push(currentNode);
3204
+ }
3205
+ }
3206
+ });
3207
+ // 辅助排序函数:按 x-sort 升序
3208
+ const sortBySort = (arr) => {
3209
+ arr.sort((a, b) => a["x-sort"] - b["x-sort"]);
3210
+ };
3211
+ // 3. 递归排序子节点
3212
+ const sortChildrenRecursively = (node) => {
3213
+ sortBySort(node.children);
3214
+ node.children.forEach((child) => sortChildrenRecursively(child));
3215
+ };
3216
+ sortBySort(roots); // 根节点排序
3217
+ roots.forEach((root) => sortChildrenRecursively(root));
3218
+ // 4. 深度优先遍历(先序)
3219
+ const result = [];
3220
+ const dfs = (node) => {
3221
+ result.push(node);
3222
+ node.children.forEach((child) => dfs(child));
3223
+ };
3224
+ roots.forEach((root) => dfs(root));
3225
+ // 5. 去除 children 字段,只保留原始属性
3226
+ return result.map(({ children, ...rest }) => rest);
3227
+ }
3228
+ sortByXSortPreserveStructure(data, ascending = true) {
3229
+ // 提取所有 (path, method, sort)
3230
+ const items = [];
3231
+ for (const [path, methods] of Object.entries(data)) {
3232
+ for (const [method, spec] of Object.entries(methods)) {
3233
+ if (spec && typeof spec === "object" && spec["x-sort"] !== undefined) {
3234
+ items.push({ path, method, sort: spec["x-sort"] });
3235
+ }
3236
+ }
3237
+ }
3238
+ // 排序
3239
+ items.sort((a, b) => (ascending ? a.sort - b.sort : b.sort - a.sort));
3240
+ // 重建对象
3241
+ const result = {};
3242
+ for (const { path, method } of items) {
3243
+ if (!result[path])
3244
+ result[path] = {};
3245
+ result[path][method] = data[path][method];
3246
+ }
3247
+ // 调试:打印排序后的 x-sort 列表
3248
+ console.log("排序后的顺序(path + method + x-sort):");
3249
+ items.forEach((item) => {
3250
+ console.log(` ${item.sort} - ${item.method} ${item.path}`);
3251
+ });
3252
+ return result;
3253
+ }
3254
+ async apiToswagger(apipostObj, version, language, options) {
3128
3255
  // 初始化语言包
3129
- await I18nInit(language || 'en');
3256
+ await I18nInit(language || "en");
3130
3257
  this.apiToSwaggerOrigin = apipostObj;
3131
3258
  this.apiToSwaggerVersion = version;
3132
3259
  this.apiToSwaggerResult = {};
@@ -3145,7 +3272,35 @@ class ApipostToSwagger {
3145
3272
  if (`${version}` === "metersphere") {
3146
3273
  this.formatData();
3147
3274
  }
3148
- return throwResult$2("success", "", this.apiToSwaggerResult);
3275
+ // 处理tags排序问题
3276
+ const tempTags = this.sortApiNodes(this.apiToSwaggerResult?.tags || []);
3277
+ // 处理paths排序
3278
+ console.log(this.apiToSwaggerResult.paths, "this.apiToSwaggerResult.paths");
3279
+ const tempPaths = this.sortByXSortPreserveStructure(this.apiToSwaggerResult?.paths);
3280
+ // this.apiToSwaggerResult.paths
3281
+ // sortBy(this.apiToSwaggerResult?.tags, ["x-sort", "x-parent-id"]);
3282
+ let result = { ...this.apiToSwaggerResult, tags: tempTags, paths: tempPaths };
3283
+ if (options) {
3284
+ if (options.includeExt === false) {
3285
+ result = stripExtensions(result);
3286
+ }
3287
+ if (options.dirAsTags === false) {
3288
+ result.tags = [];
3289
+ if (result.paths && typeof result.paths === "object") {
3290
+ for (const p of Object.keys(result.paths)) {
3291
+ const ms = result.paths[p];
3292
+ if (ms && typeof ms === "object") {
3293
+ for (const m of Object.keys(ms)) {
3294
+ if (ms[m] && Array.isArray(ms[m].tags)) {
3295
+ ms[m].tags = [];
3296
+ }
3297
+ }
3298
+ }
3299
+ }
3300
+ }
3301
+ }
3302
+ }
3303
+ return throwResult$2("success", "", result);
3149
3304
  }
3150
3305
  catch (error) {
3151
3306
  console.log(JSON.stringify(error.message), "error");
@@ -4355,6 +4510,199 @@ class ApidocToApipost {
4355
4510
  }
4356
4511
  }
4357
4512
 
4513
+ const DEFAULT_FIELD_TYPE$3 = ["string", "integer", "boolean", "number", "array"];
4514
+ const completionApiTargetMark = (status) => {
4515
+ if (DEFAULT_DEVELOP_ENUM.includes(status)) {
4516
+ return "1";
4517
+ }
4518
+ if (DEFAULT_COMPLETE_ENUM.includes(status)) {
4519
+ return "2";
4520
+ }
4521
+ if (DEFAULT_EDIT_ENUM.includes(status)) {
4522
+ return "3";
4523
+ }
4524
+ if (DEFAULT_DISCARD_ENUM.includes(status)) {
4525
+ return "4";
4526
+ }
4527
+ return "1";
4528
+ };
4529
+ const completionParameter = (parameter) => {
4530
+ if (lodash.isArray(parameter)) {
4531
+ return parameter?.map((item) => ({
4532
+ param_id: apipostTools.snowflakeId(),
4533
+ description: item?.description || "",
4534
+ field_type: lodash.has(item, "type") && DEFAULT_FIELD_TYPE$3?.includes(item?.type)
4535
+ ? item.type.charAt(0).toUpperCase() + item.type.slice(1)
4536
+ : "String",
4537
+ is_checked: lodash.has(item, 'enable') ? (item?.enable ? 1 : -1) : 1,
4538
+ key: item?.name || item?.relatedName || "",
4539
+ value: item?.example || item?.value || "",
4540
+ not_null: item?.required ? 1 : -1,
4541
+ schema: item?.schema || {}
4542
+ }));
4543
+ }
4544
+ return [];
4545
+ };
4546
+ // const websocket2SendType = {
4547
+ // "text":"text",
4548
+ // "json":"json",
4549
+ // "xml":"xml",
4550
+ // "html":"html",
4551
+ // "base64":"base64",
4552
+ // "hexadecimal":"hexadecimal"
4553
+ // }
4554
+ const completionWebsocketTarget = (item, baseInfo, parentInfo) => {
4555
+ const { api } = item || {};
4556
+ let apifoxApi = api;
4557
+ let queryParameter = [];
4558
+ if (lodash.isArray(apifoxApi?.parameters?.query)) {
4559
+ queryParameter = completionParameter(apifoxApi?.parameters?.query);
4560
+ }
4561
+ return {
4562
+ ...baseInfo,
4563
+ parent_id: parentInfo?.target_id || "0",
4564
+ target_type: 'websocket2',
4565
+ name: getSubstring(item?.name || apifoxApi?.name, 255) || "Unnamed WS Connection",
4566
+ sort: 0,
4567
+ version: 0,
4568
+ mark_id: completionApiTargetMark(apifoxApi?.status),
4569
+ status: 1,
4570
+ is_changed: -1,
4571
+ is_create: 1,
4572
+ method: '',
4573
+ request: {
4574
+ cookie: {
4575
+ parameter: lodash.isArray(apifoxApi?.parameters?.cookie) ? completionParameter(apifoxApi?.parameters?.cookie) : [],
4576
+ },
4577
+ header: {
4578
+ parameter: lodash.isArray(apifoxApi?.parameters?.header) ? completionParameter(apifoxApi?.parameters?.header) : [],
4579
+ },
4580
+ query: {
4581
+ parameter: queryParameter,
4582
+ },
4583
+ },
4584
+ message: [{
4585
+ name: 'Message',
4586
+ param_id: apipostTools.snowflakeId(),
4587
+ request: {
4588
+ mode: apifoxApi?.requestBody?.messageType || 'text',
4589
+ raw: apifoxApi?.requestBody?.message || '',
4590
+ raw_parameter: [],
4591
+ raw_schema: { type: 'object' },
4592
+ },
4593
+ response: {
4594
+ mode: 'text',
4595
+ raw: '',
4596
+ raw_parameter: [],
4597
+ raw_schema: { type: 'object' },
4598
+ },
4599
+ }],
4600
+ url: apifoxApi?.path || "",
4601
+ description: apifoxApi?.description || "",
4602
+ attribute_info: {},
4603
+ tags: lodash.isArray(apifoxApi?.tags) ? apifoxApi?.tags : [],
4604
+ config: {
4605
+ certificate_verification: apifoxApi?.advancedSettings?.SSLValidate === true ? 1 : -1,
4606
+ information_size: 5,
4607
+ reconnect_num: 5,
4608
+ reconnect_time: 5000,
4609
+ // shake_hands_path: '',
4610
+ shake_hands_timeout: 0,
4611
+ // socket_version: 'v4',
4612
+ },
4613
+ };
4614
+ };
4615
+ const completionSocketIoTarget = (item, baseInfo, parentInfo) => {
4616
+ const { api } = item || {};
4617
+ return {
4618
+ ...baseInfo,
4619
+ parent_id: parentInfo?.target_id || "0",
4620
+ target_type: 'socketio',
4621
+ name: getSubstring(item?.name || api?.name, 255) || "Unnamed Socket.IO Session",
4622
+ sort: 0,
4623
+ version: 0,
4624
+ mark_id: completionApiTargetMark(api?.status),
4625
+ status: 1,
4626
+ is_changed: -1,
4627
+ is_create: 1,
4628
+ method: '',
4629
+ request: {
4630
+ cookie: {
4631
+ parameter: lodash.isArray(api?.parameters?.cookie) ? completionParameter(api?.parameters?.cookie) : [],
4632
+ },
4633
+ header: {
4634
+ parameter: lodash.isArray(api?.parameters?.header) ? completionParameter(api?.parameters?.header) : [],
4635
+ },
4636
+ query: {
4637
+ parameter: lodash.isArray(api?.parameters?.query) ? completionParameter(api?.parameters?.query) : [],
4638
+ },
4639
+ event: {
4640
+ parameter: lodash.isArray(api?.events) ? api.events.map(e => {
4641
+ return {
4642
+ description: e?.description || '',
4643
+ field_type: "string",
4644
+ is_checked: 1,
4645
+ key: e?.name || "",
4646
+ value: e?.listen ? "1" : '',
4647
+ not_null: 1,
4648
+ schema: {
4649
+ type: "string"
4650
+ },
4651
+ param_id: apipostTools.snowflakeId()
4652
+ };
4653
+ }) : [],
4654
+ },
4655
+ },
4656
+ message: lodash.isArray(api?.requestBody?.args) ? api.requestBody.args.map((arg, index) => {
4657
+ return {
4658
+ name: `Message${index + 1}`,
4659
+ param_id: apipostTools.snowflakeId(),
4660
+ request: {
4661
+ mode: arg?.type || 'text',
4662
+ raw: arg?.content || '',
4663
+ raw_parameter: [],
4664
+ raw_schema: { type: 'object' },
4665
+ },
4666
+ response: {
4667
+ mode: 'text',
4668
+ raw: '',
4669
+ raw_parameter: [],
4670
+ raw_schema: { type: 'object' },
4671
+ },
4672
+ };
4673
+ }) : [{
4674
+ name: 'Message',
4675
+ param_id: apipostTools.snowflakeId(),
4676
+ request: {
4677
+ mode: 'text',
4678
+ raw: '',
4679
+ raw_parameter: [],
4680
+ raw_schema: { type: 'object' },
4681
+ },
4682
+ response: {
4683
+ mode: 'text',
4684
+ raw: '',
4685
+ raw_parameter: [],
4686
+ raw_schema: { type: 'object' },
4687
+ },
4688
+ }],
4689
+ url: api?.path || "",
4690
+ description: api?.description || '',
4691
+ attribute_info: {},
4692
+ tags: lodash.isArray(api?.tags) ? api?.tags : [],
4693
+ config: {
4694
+ reconnect_num: 5,
4695
+ reconnect_time: 5000,
4696
+ shake_hands_path: api?.advancedSettings?.handshakePath ? api.advancedSettings.handshakePath : '/socket.io',
4697
+ shake_hands_timeout: 0,
4698
+ socket_version: api?.advancedSettings?.clientVersion ? `v${api.advancedSettings.clientVersion}` : 'v4',
4699
+ certificate_verification: api?.advancedSettings?.SSLValidate ? 1 : -1,
4700
+ },
4701
+ ask: api?.requestBody?.ack ? 1 : -1,
4702
+ msg_data: api?.requestBody?.eventName ? api?.requestBody?.eventName : ''
4703
+ };
4704
+ };
4705
+
4358
4706
  // @ts-nocheck
4359
4707
  const throwResult$1 = (status, message, data = "") => {
4360
4708
  return {
@@ -4473,6 +4821,12 @@ class ApifoxToApipost {
4473
4821
  writable: true,
4474
4822
  value: void 0
4475
4823
  });
4824
+ Object.defineProperty(this, "folderNameMap", {
4825
+ enumerable: true,
4826
+ configurable: true,
4827
+ writable: true,
4828
+ value: void 0
4829
+ });
4476
4830
  Object.defineProperty(this, "apisMap", {
4477
4831
  enumerable: true,
4478
4832
  configurable: true,
@@ -4503,6 +4857,18 @@ class ApifoxToApipost {
4503
4857
  writable: true,
4504
4858
  value: void 0
4505
4859
  });
4860
+ Object.defineProperty(this, "apifoxApiIdMap", {
4861
+ enumerable: true,
4862
+ configurable: true,
4863
+ writable: true,
4864
+ value: void 0
4865
+ });
4866
+ Object.defineProperty(this, "config", {
4867
+ enumerable: true,
4868
+ configurable: true,
4869
+ writable: true,
4870
+ value: void 0
4871
+ });
4506
4872
  Object.defineProperty(this, "recursionSchema", {
4507
4873
  enumerable: true,
4508
4874
  configurable: true,
@@ -4564,6 +4930,10 @@ class ApifoxToApipost {
4564
4930
  mock_custom_rules: [],
4565
4931
  db_link: [],
4566
4932
  };
4933
+ this.config = {
4934
+ project_id: "",
4935
+ unrelated_id: false
4936
+ };
4567
4937
  this.apis = [];
4568
4938
  this.models = [];
4569
4939
  this.samples = [];
@@ -4572,11 +4942,13 @@ class ApifoxToApipost {
4572
4942
  this.serversMap = {};
4573
4943
  this.modelMap = {};
4574
4944
  this.foldersMap = { "0": "0" };
4945
+ this.folderNameMap = {};
4575
4946
  this.commonScripts = [];
4576
4947
  this.apisMap = {};
4577
4948
  this.modelIdMap = {};
4578
4949
  this.dbLinkmap = {};
4579
4950
  this.envsMap = {};
4951
+ this.apifoxApiIdMap = {};
4580
4952
  }
4581
4953
  validate(json) {
4582
4954
  if (lodash.has(json, "apifoxProject")) {
@@ -4618,6 +4990,10 @@ class ApifoxToApipost {
4618
4990
  mock_custom_rules: [],
4619
4991
  db_link: [],
4620
4992
  };
4993
+ this.config = {
4994
+ project_id: "",
4995
+ unrelated_id: false
4996
+ };
4621
4997
  this.apis = [];
4622
4998
  this.models = [];
4623
4999
  this.samples = [];
@@ -4625,10 +5001,12 @@ class ApifoxToApipost {
4625
5001
  this.serversMap = {};
4626
5002
  this.modelMap = {};
4627
5003
  this.foldersMap = { "0": "0" };
5004
+ this.folderNameMap = {};
4628
5005
  this.apisMap = {};
4629
5006
  this.modelIdMap = {};
4630
5007
  this.dbLinkmap = {};
4631
5008
  this.envsMap = {};
5009
+ this.apifoxApiIdMap = {};
4632
5010
  }
4633
5011
  initProject(json, project_id) {
4634
5012
  this.project.name = getSubstring(json?.info?.name, 64) || "New Project";
@@ -4924,7 +5302,7 @@ class ApifoxToApipost {
4924
5302
  let model_id = apipostTools.snowflakeId();
4925
5303
  if (lodash.isString(item?.id)) {
4926
5304
  let refId = item.id.split('/').pop();
4927
- model_id = refId ? hexSnowflake(refId) : model_id;
5305
+ model_id = refId ? hexSnowflake(refId, this.config.unrelated_id) : model_id;
4928
5306
  }
4929
5307
  if (!lodash.has(this.modelIdMap, model_id)) {
4930
5308
  this.modelIdMap[model_id] = model_id;
@@ -5332,6 +5710,10 @@ class ApifoxToApipost {
5332
5710
  body["raw"] = requestBody?.example || requestBody?.data || "";
5333
5711
  }
5334
5712
  }
5713
+ else if (!requestBody?.[type] && requestBody?.data) {
5714
+ body["mode"] = "plain";
5715
+ body["raw"] = requestBody?.data || "";
5716
+ }
5335
5717
  return {
5336
5718
  mode: "none",
5337
5719
  parameter: [],
@@ -5357,6 +5739,63 @@ class ApifoxToApipost {
5357
5739
  binary: {},
5358
5740
  };
5359
5741
  }
5742
+ completionTcpRequestBody(requestBody, type = "type") {
5743
+ if (requestBody && isObject(requestBody)) {
5744
+ let foxMode = requestBody?.[type] || 'text';
5745
+ return {
5746
+ mode: foxMode === "raw" ? "text" : foxMode,
5747
+ "parameter": [
5748
+ {
5749
+ "definition": "",
5750
+ "key": "",
5751
+ "value": "",
5752
+ "description": "",
5753
+ "is_checked": 1,
5754
+ "param_id": "309780acf12016",
5755
+ "static": true,
5756
+ "rules": {
5757
+ "common": "",
5758
+ "content_type": "custom",
5759
+ "custom": "",
5760
+ "fill_type": "",
5761
+ "length": 0,
5762
+ "delimiter": ""
5763
+ }
5764
+ }
5765
+ ],
5766
+ "raw": requestBody?.example || "",
5767
+ "raw_parameter": [],
5768
+ "raw_schema": this.recursionSchema(requestBody?.jsonSchema || { type: "object", properties: {} }, this.modelMap)
5769
+ };
5770
+ }
5771
+ return {
5772
+ "mode": "xml",
5773
+ "parameter": [
5774
+ {
5775
+ "definition": "",
5776
+ "key": "",
5777
+ "value": "",
5778
+ "description": "",
5779
+ "is_checked": 1,
5780
+ "param_id": "309780acf12016",
5781
+ "static": true,
5782
+ "rules": {
5783
+ "common": "",
5784
+ "content_type": "custom",
5785
+ "custom": "",
5786
+ "fill_type": "",
5787
+ "length": 0,
5788
+ "delimiter": ""
5789
+ }
5790
+ }
5791
+ ],
5792
+ "raw": "",
5793
+ "raw_parameter": [],
5794
+ "raw_schema": {
5795
+ "type": "object"
5796
+ }
5797
+ };
5798
+ }
5360
5799
  completionApiRequest(item, requestBody, apiRequestBody) {
5361
5800
  return {
5362
5801
  auth: this.completionApiRequestAuth(item?.auth),
@@ -5380,7 +5819,7 @@ class ApifoxToApipost {
5380
5819
  completionApiFolder(item, parentInfo) {
5381
5820
  let target_id = apipostTools.snowflakeId();
5382
5821
  if (lodash.has(item, 'id')) {
5383
- target_id = hexSnowflake(item?.id);
5822
+ target_id = hexSnowflake(item?.id, this.config.unrelated_id);
5384
5823
  }
5385
5824
  if (item?.id) {
5386
5825
  this.foldersMap[item.id] = target_id;
@@ -5430,7 +5869,7 @@ class ApifoxToApipost {
5430
5869
  // );
5431
5870
  return {
5432
5871
  example_id: apipostTools.snowflakeId(),
5433
- raw: raw ? getBeautifulRaw$1(raw?.data || "") : "",
5872
+ raw: raw ? getBeautifulRaw$1(raw?.data || raw?.content || "") : "",
5434
5873
  raw_parameter: [],
5435
5874
  expect: {
5436
5875
  name: getSubstring(item?.name, 255) || "",
@@ -5471,7 +5910,13 @@ class ApifoxToApipost {
5471
5910
  const { api, customHttpRequest } = item || {};
5472
5911
  let apifoxApi = api || customHttpRequest;
5473
5912
  if (lodash.has(apifoxApi, 'id')) {
5474
- baseInfo.target_id = hexSnowflake(apifoxApi?.id);
5913
+ if (lodash.has(this.apifoxApiIdMap, String(apifoxApi?.id))) {
5914
+ baseInfo.target_id = this.apifoxApiIdMap[String(apifoxApi.id)];
5915
+ }
5916
+ else {
5917
+ baseInfo.target_id = hexSnowflake(apifoxApi?.id, this.config.unrelated_id);
5918
+ this.apifoxApiIdMap[String(apifoxApi.id)] = baseInfo.target_id;
5919
+ }
5475
5920
  }
5476
5921
  if (apifoxApi?.requestBody?.type === 'graphql') {
5477
5922
  const request = this.completionApiRequest({
@@ -5532,7 +5977,7 @@ class ApifoxToApipost {
5532
5977
  cases?.forEach((caseItem) => {
5533
5978
  let sample_id = apipostTools.snowflakeId();
5534
5979
  if (lodash.has(caseItem, 'id')) {
5535
- sample_id = hexSnowflake(caseItem?.id);
5980
+ sample_id = hexSnowflake(caseItem?.id, this.config.unrelated_id);
5536
5981
  }
5537
5982
  if (!lodash.has(this.apisMap, sample_id)) {
5538
5983
  this.apisMap[sample_id] = sample_id;
@@ -5573,6 +6018,10 @@ class ApifoxToApipost {
5573
6018
  if (lodash.has(item, "items") && !lodash.has(item, "api")) {
5574
6019
  // 这是目录操作
5575
6020
  const parent = this.completionApiFolder(item, parentInfo);
6021
+ // 记录以目录名称为key的对象
6022
+ if (!lodash.has(this.folderNameMap, parent.name)) {
6023
+ this.folderNameMap[parent.name] = parent;
6024
+ }
5576
6025
  if (!lodash.has(this.apisMap, parent.target_id)) {
5577
6026
  this.apisMap[parent.target_id] = parent.target_id;
5578
6027
  pre.push(parent);
@@ -5602,7 +6051,7 @@ class ApifoxToApipost {
5602
6051
  }
5603
6052
  return [];
5604
6053
  }
5605
- completionEventList(steps, parentEventId = '0', result = [], testing_id) {
6054
+ completionEventList(steps, parentEventId = '0', result = [], testing_id, apis = []) {
5606
6055
  let sortCounter = 1;
5607
6056
  // 记录上一个if类型数据, 主要用来生成else的数据
5608
6057
  const ifStack = [];
@@ -5726,17 +6175,39 @@ class ApifoxToApipost {
5726
6175
  mappedType = "api";
5727
6176
  // 这是接口操作
5728
6177
  const base = {
5729
- target_id: hexSnowflake(item?.bindId),
6178
+ target_id: hexSnowflake(item?.bindId, this.config.unrelated_id),
5730
6179
  project_id: this.project.project_id || "",
5731
6180
  };
5732
- // 判断接口列表中是否有
6181
+ // 判断接口列表中是否有重复id的接口
5733
6182
  const targetApi = this.apis.find(i => i?.target_id === base.target_id);
5734
6183
  let apiData = {};
5735
6184
  if (lodash.isPlainObject(item?.httpApiCase)) {
5736
- const targetData = this.completionApiTarget({
5737
- name: item?.httpApiCase?.name || item?.name,
6185
+ let httpApiCaseData = {
6186
+ name: item?.name || item?.httpApiCase?.name,
5738
6187
  api: { ...item?.httpApiCase, id: item?.httpApiCase?.apiId || item?.bindId }
5739
- }, base);
6188
+ };
6189
+ const newId = this.apifoxApiIdMap[String(httpApiCaseData.api.id)];
6190
+ // 获取接口列表中的接口
6191
+ const targetApiData = this.apis.find(i => i?.target_id === newId);
6192
+ if (targetApiData !== undefined) {
6193
+ // 补齐url
6194
+ if ((httpApiCaseData.api.path === null || !httpApiCaseData?.api?.path)) {
6195
+ httpApiCaseData.api.path = targetApiData.url;
6196
+ }
6197
+ // 补齐method
6198
+ if ((httpApiCaseData.api.method === null || !httpApiCaseData?.api?.method)) {
6199
+ httpApiCaseData.api.method = targetApiData.method;
6200
+ }
6201
+ // 判断名字是否需要拼接
6202
+ if (!item?.name && targetApiData.name !== httpApiCaseData.name) {
6203
+ httpApiCaseData.name = `${targetApiData.name}(${httpApiCaseData.name})`;
6204
+ }
6205
+ // 补齐body 的mode
6206
+ if (httpApiCaseData?.api?.requestBody && !httpApiCaseData?.api?.requestBody?.type && targetApiData?.body?.mode) {
6207
+ httpApiCaseData.api.requestBody.type = MODE_TYPE2[targetApiData?.body?.mode] || '';
6208
+ }
6209
+ }
6210
+ const targetData = this.completionApiTarget(httpApiCaseData, base);
5740
6211
  apiData = targetData;
5741
6212
  }
5742
6213
  else if (targetApi === undefined) {
@@ -5758,6 +6229,8 @@ class ApifoxToApipost {
5758
6229
  };
5759
6230
  if (!lodash.has(this.apisMap, apiData.target_id)) {
5760
6231
  this.apisMap[apiData.target_id] = apiData.target_id;
6232
+ // 接口列表不存在的接口
6233
+ apis.push(apiData);
5761
6234
  }
5762
6235
  // 自动同步
5763
6236
  if (item?.syncMode === 'SYNC_WITH_API') {
@@ -5815,7 +6288,7 @@ class ApifoxToApipost {
5815
6288
  result.push(currentItem);
5816
6289
  // 2. 处理子项(steps/children/items)
5817
6290
  if (isArray(item.children)) {
5818
- this.completionEventList(item.children, currentItem.event_id, result, testing_id);
6291
+ this.completionEventList(item.children, currentItem.event_id, result, testing_id, apis);
5819
6292
  }
5820
6293
  });
5821
6294
  return result;
@@ -5825,7 +6298,7 @@ class ApifoxToApipost {
5825
6298
  // 1. 处理目录(folder类型)
5826
6299
  if ((isArray(item.children) || isArray(item.items)) && !lodash.has(item, 'steps')) {
5827
6300
  const folder = {
5828
- testing_id: hexSnowflake(item?.id), // 如果没有id则生成一个
6301
+ testing_id: hexSnowflake(item?.id, this.config.unrelated_id), // 如果没有id则生成一个
5829
6302
  parent_id: parentId,
5830
6303
  testing_type: 'folder',
5831
6304
  name: item.name || 'Unnamed Folder',
@@ -5850,14 +6323,15 @@ class ApifoxToApipost {
5850
6323
  eventList: [],
5851
6324
  tags: isArray(item?.tags) ? item.tags : [],
5852
6325
  options: item?.options || {},
5853
- apiTestDataSets: item?.apiTestDataSets || []
6326
+ apiTestDataSets: item?.apiTestDataSets || [],
6327
+ apis: [],
5854
6328
  };
5855
6329
  let foxEnvironmentId = String(item?.options?.environmentId);
5856
6330
  if (lodash.has(this.envsMap, foxEnvironmentId)) {
5857
6331
  // 替换新的环境ID
5858
6332
  item.options.environmentId = this.envsMap[foxEnvironmentId];
5859
6333
  }
5860
- caseData.eventList = this.completionEventList(item.steps, '0', [], caseData.testing_id);
6334
+ caseData.eventList = this.completionEventList(item.steps, '0', [], caseData.testing_id, caseData.apis);
5861
6335
  result.push(caseData);
5862
6336
  }
5863
6337
  });
@@ -5869,6 +6343,102 @@ class ApifoxToApipost {
5869
6343
  this.apis = this.completionApis(root?.items);
5870
6344
  }
5871
6345
  }
6346
+ initWebSocket(wsCollection) {
6347
+ const root = wsCollection?.[0];
6348
+ if (root?.items && isArray(root?.items)) {
6349
+ this.apis = this.apis.concat(this.completionWebsockets(root?.items));
6350
+ }
6351
+ }
6352
+ completionWebsockets(items, parentInfo) {
6353
+ if (items?.length) {
6354
+ return items?.reduce((pre, item) => {
6355
+ if (lodash.has(item, "items") && !lodash.has(item, "api")) {
6356
+ // 这是目录操作
6357
+ let parent = this.completionApiFolder(item, parentInfo);
6358
+ // 记录以目录名称为key的对象 没有目录才新建目录,有的话直接把ws放到该目录下
6359
+ if (!lodash.has(this.folderNameMap, parent.name)) {
6360
+ this.folderNameMap[parent.name] = parent;
6361
+ }
6362
+ else {
6363
+ parent = this.folderNameMap[parent.name];
6364
+ pre = pre.concat(this.completionWebsockets(item?.items, parent));
6365
+ return pre;
6366
+ }
6367
+ if (!lodash.has(this.apisMap, parent.target_id)) {
6368
+ this.apisMap[parent.target_id] = parent.target_id;
6369
+ pre.push(parent);
6370
+ }
6371
+ else {
6372
+ return pre;
6373
+ // 重复id数据 先忽略
6374
+ }
6375
+ pre = pre.concat(this.completionWebsockets(item?.items, parent));
6376
+ }
6377
+ if (!lodash.has(item, "items") && lodash.has(item, "api")) {
6378
+ // 这是接口操作
6379
+ const base = {
6380
+ target_id: apipostTools.snowflakeId(),
6381
+ project_id: this.project.project_id || "",
6382
+ };
6383
+ const target = completionWebsocketTarget(item, base, parentInfo);
6384
+ if (!lodash.has(this.apisMap, target.target_id)) {
6385
+ this.apisMap[target.target_id] = target.target_id;
6386
+ pre.push(target);
6387
+ }
6388
+ }
6389
+ return pre;
6390
+ }, []);
6391
+ }
6392
+ return [];
6393
+ }
6394
+ initSocketIo(socketIOCollection) {
6395
+ const root = socketIOCollection?.[0];
6396
+ if (root?.items && isArray(root?.items)) {
6397
+ this.apis = this.apis.concat(this.completionSocketIo(root?.items));
6398
+ }
6399
+ }
6400
+ completionSocketIo(items, parentInfo) {
6401
+ if (items?.length) {
6402
+ return items?.reduce((pre, item) => {
6403
+ if (lodash.has(item, "items") && !lodash.has(item, "api")) {
6404
+ // 这是目录操作
6405
+ let parent = this.completionApiFolder(item, parentInfo);
6406
+ // 记录以目录名称为key的对象 没有目录才新建目录,有的话直接把ws放到该目录下
6407
+ if (!lodash.has(this.folderNameMap, parent.name)) {
6408
+ this.folderNameMap[parent.name] = parent;
6409
+ }
6410
+ else {
6411
+ parent = this.folderNameMap[parent.name];
6412
+ pre = pre.concat(this.completionSocketIo(item?.items, parent));
6413
+ return pre;
6414
+ }
6415
+ if (!lodash.has(this.apisMap, parent.target_id)) {
6416
+ this.apisMap[parent.target_id] = parent.target_id;
6417
+ pre.push(parent);
6418
+ }
6419
+ else {
6420
+ return pre;
6421
+ // 重复id数据 先忽略
6422
+ }
6423
+ pre = pre.concat(this.completionSocketIo(item?.items, parent));
6424
+ }
6425
+ if (!lodash.has(item, "items") && lodash.has(item, "api")) {
6426
+ // 这是接口操作
6427
+ const base = {
6428
+ target_id: apipostTools.snowflakeId(),
6429
+ project_id: this.project.project_id || "",
6430
+ };
6431
+ const target = completionSocketIoTarget(item, base, parentInfo);
6432
+ if (!lodash.has(this.apisMap, target.target_id)) {
6433
+ this.apisMap[target.target_id] = target.target_id;
6434
+ pre.push(target);
6435
+ }
6436
+ }
6437
+ return pre;
6438
+ }, []);
6439
+ }
6440
+ return [];
6441
+ }
5872
6442
  completionDocs(items) {
5873
6443
  if (items?.length) {
5874
6444
  return items?.reduce((pre, item) => {
@@ -5933,13 +6503,32 @@ class ApifoxToApipost {
5933
6503
  };
5934
6504
  }
5935
6505
  completionTcpMethodRequest(parameter) {
6506
+ const funcRequest = [];
6507
+ if (isArray(parameter?.dataProcessors)) {
6508
+ lodash.forEach(parameter.dataProcessors, (item) => {
6509
+ if (item?.id == 101) {
6510
+ funcRequest.push({
6511
+ "id": "addCharToPacketEnd",
6512
+ "title": "包尾添加特殊字符",
6513
+ "option": "\\n"
6514
+ });
6515
+ }
6516
+ if (item?.id == 102) {
6517
+ funcRequest.push({
6518
+ "id": "calcLengthToPacketHeader",
6519
+ "title": "计算内容长度并添加到包头(文本)",
6520
+ "option": item?.options?.headerLength || 8
6521
+ });
6522
+ }
6523
+ });
6524
+ }
5936
6525
  return {
5937
- body: this.completionApiRequestBody(parameter, "contentType"),
6526
+ body: this.completionTcpRequestBody(parameter, "contentType"),
5938
6527
  post_tasks: [],
5939
6528
  configs: {
5940
6529
  charset: "utf8",
5941
6530
  func: {
5942
- request: [],
6531
+ request: funcRequest,
5943
6532
  response: [],
5944
6533
  },
5945
6534
  },
@@ -6005,19 +6594,25 @@ class ApifoxToApipost {
6005
6594
  initTestCase(apiTestCaseCollection) {
6006
6595
  // 判断是否有测试用例数据
6007
6596
  if (isArray(apiTestCaseCollection) && apiTestCaseCollection.length > 0 && isArray(apiTestCaseCollection[0]?.items)) {
6008
- this.test_cases = this.completionTestCases(apiTestCaseCollection[0].items);
6597
+ this.test_cases = this.completionTestCases(apiTestCaseCollection[0].items.concat(isArray(apiTestCaseCollection[0]?.children) ? apiTestCaseCollection[0].children : []));
6009
6598
  }
6010
6599
  }
6011
- convert(json, project_id) {
6600
+ convert(json, config = {
6601
+ project_id: "",
6602
+ unrelated_id: false
6603
+ }) {
6012
6604
  this.clear();
6013
6605
  try {
6606
+ this.config = config;
6014
6607
  this.validate(json);
6015
- this.initProject(json, project_id);
6608
+ this.initProject(json, config?.project_id);
6016
6609
  this.initGlobal(json);
6017
6610
  this.initModels(json?.schemaCollection);
6018
6611
  this.initApis(json?.apiCollection);
6019
6612
  this.initDoc(json?.docCollection);
6020
6613
  this.initTcp(json?.socketCollection);
6614
+ this.initWebSocket(json?.webSocketCollection);
6615
+ this.initSocketIo(json?.socketIOCollection);
6021
6616
  this.initTestCase(json?.apiTestCaseCollection);
6022
6617
  const data = {
6023
6618
  ...this.project,
@@ -6029,7 +6624,7 @@ class ApifoxToApipost {
6029
6624
  samples: this.samples,
6030
6625
  test_cases: this.test_cases,
6031
6626
  };
6032
- // console.log(JSON.stringify(data.test_cases[1]));
6627
+ // console.log(JSON.stringify(this.apis));
6033
6628
  return throwResult$1("success", "", data);
6034
6629
  }
6035
6630
  catch (err) {
@@ -6153,6 +6748,18 @@ class ApifoxcliToApipost {
6153
6748
  writable: true,
6154
6749
  value: void 0
6155
6750
  });
6751
+ Object.defineProperty(this, "config", {
6752
+ enumerable: true,
6753
+ configurable: true,
6754
+ writable: true,
6755
+ value: void 0
6756
+ });
6757
+ Object.defineProperty(this, "apifoxApiIdMap", {
6758
+ enumerable: true,
6759
+ configurable: true,
6760
+ writable: true,
6761
+ value: void 0
6762
+ });
6156
6763
  Object.defineProperty(this, "recursionSchema", {
6157
6764
  enumerable: true,
6158
6765
  configurable: true,
@@ -6213,6 +6820,10 @@ class ApifoxcliToApipost {
6213
6820
  mock_custom_rules: [],
6214
6821
  db_link: [],
6215
6822
  };
6823
+ this.config = {
6824
+ project_id: "",
6825
+ unrelated_id: false
6826
+ };
6216
6827
  this.apis = [];
6217
6828
  this.eventList = [];
6218
6829
  this.models = [];
@@ -6224,6 +6835,7 @@ class ApifoxcliToApipost {
6224
6835
  this.foldersMap = { "0": "0" };
6225
6836
  this.commonScripts = [];
6226
6837
  this.modelIdMap = {};
6838
+ this.apifoxApiIdMap = {};
6227
6839
  }
6228
6840
  validate(json) {
6229
6841
  if (lodash.has(json, "apifoxCli")) {
@@ -6259,6 +6871,10 @@ class ApifoxcliToApipost {
6259
6871
  mock_custom_rules: [],
6260
6872
  db_link: [],
6261
6873
  };
6874
+ this.config = {
6875
+ project_id: "",
6876
+ unrelated_id: false
6877
+ };
6262
6878
  this.apis = [];
6263
6879
  this.eventList = [];
6264
6880
  this.models = [];
@@ -6268,6 +6884,7 @@ class ApifoxcliToApipost {
6268
6884
  this.modelMap = {};
6269
6885
  this.foldersMap = { "0": "0" };
6270
6886
  this.modelIdMap = {};
6887
+ this.apifoxApiIdMap = {};
6271
6888
  }
6272
6889
  initProject(json, project_id) {
6273
6890
  // this.project.testing_type = "testing";
@@ -6418,7 +7035,7 @@ class ApifoxcliToApipost {
6418
7035
  if (key) {
6419
7036
  // 这是模型操作
6420
7037
  // 这里要做Map映射 引用ref替换使用
6421
- const model_id = hexSnowflake(key);
7038
+ const model_id = hexSnowflake(key, this.config.unrelated_id);
6422
7039
  if (!lodash.has(this.modelIdMap, model_id)) {
6423
7040
  this.modelIdMap[model_id] = model_id;
6424
7041
  }
@@ -6906,7 +7523,7 @@ class ApifoxcliToApipost {
6906
7523
  completionApiFolder(item, parentInfo) {
6907
7524
  let target_id = apipostTools.snowflakeId();
6908
7525
  if (lodash.has(item, 'id')) {
6909
- target_id = hexSnowflake(item?.id);
7526
+ target_id = hexSnowflake(item?.id, this.config.unrelated_id);
6910
7527
  }
6911
7528
  if (item?.id) {
6912
7529
  this.foldersMap[item.id] = target_id;
@@ -7018,7 +7635,13 @@ class ApifoxcliToApipost {
7018
7635
  completionApiTarget(item, baseInfo) {
7019
7636
  const { request, response, responseDefinition, requestDefinition, metaInfo } = item || {};
7020
7637
  if (lodash.has(metaInfo, 'httpApiId')) {
7021
- baseInfo.target_id = hexSnowflake(metaInfo?.httpApiId);
7638
+ if (lodash.has(this.apifoxApiIdMap, String(metaInfo?.httpApiId))) {
7639
+ baseInfo.target_id = this.apifoxApiIdMap[String(metaInfo.httpApiId)];
7640
+ }
7641
+ else {
7642
+ baseInfo.target_id = hexSnowflake(metaInfo?.httpApiId, this.config.unrelated_id);
7643
+ this.apifoxApiIdMap[String(metaInfo.httpApiId)] = baseInfo.target_id;
7644
+ }
7022
7645
  }
7023
7646
  return {
7024
7647
  ...baseInfo,
@@ -7048,7 +7671,7 @@ class ApifoxcliToApipost {
7048
7671
  return cases?.map((caseItem) => {
7049
7672
  let sample_id = apipostTools.snowflakeId();
7050
7673
  if (lodash.has(caseItem, 'id')) {
7051
- sample_id = hexSnowflake(caseItem?.id);
7674
+ sample_id = hexSnowflake(caseItem?.id, this.config.unrelated_id);
7052
7675
  }
7053
7676
  return {
7054
7677
  ...baseInfo,
@@ -7424,11 +8047,15 @@ class ApifoxcliToApipost {
7424
8047
  }
7425
8048
  return [];
7426
8049
  }
7427
- convert(json, project_id) {
8050
+ convert(json, config = {
8051
+ project_id: "",
8052
+ unrelated_id: false
8053
+ }) {
7428
8054
  this.clear();
7429
8055
  try {
8056
+ this.config = config;
7430
8057
  this.validate(json);
7431
- this.initProject(json, project_id);
8058
+ this.initProject(json, config?.project_id);
7432
8059
  this.initGlobal(json);
7433
8060
  this.initModels(json?.dataSchemas);
7434
8061
  this.initEventList(json?.item);