@qwe8652591/abap-recursive-query 1.1.0

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 (210) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +223 -0
  3. package/dist/cli/consumer-cli.d.ts +8 -0
  4. package/dist/cli/consumer-cli.d.ts.map +1 -0
  5. package/dist/cli/consumer-cli.js +180 -0
  6. package/dist/cli/producer-cli.d.ts +8 -0
  7. package/dist/cli/producer-cli.d.ts.map +1 -0
  8. package/dist/cli/producer-cli.js +249 -0
  9. package/dist/cli/query-object.d.ts +3 -0
  10. package/dist/cli/query-object.d.ts.map +1 -0
  11. package/dist/cli/query-object.js +486 -0
  12. package/dist/common/FilterCache.d.ts +62 -0
  13. package/dist/common/FilterCache.d.ts.map +1 -0
  14. package/dist/common/FilterCache.js +119 -0
  15. package/dist/common/RedisQueueManager.d.ts +170 -0
  16. package/dist/common/RedisQueueManager.d.ts.map +1 -0
  17. package/dist/common/RedisQueueManager.js +663 -0
  18. package/dist/common/abapStructures.d.ts +391 -0
  19. package/dist/common/abapStructures.d.ts.map +1 -0
  20. package/dist/common/abapStructures.js +2 -0
  21. package/dist/common/config.d.ts +66 -0
  22. package/dist/common/config.d.ts.map +1 -0
  23. package/dist/common/config.js +56 -0
  24. package/dist/common/index.d.ts +13 -0
  25. package/dist/common/index.d.ts.map +1 -0
  26. package/dist/common/index.js +38 -0
  27. package/dist/common/recursiveQueryConfig.d.ts +77 -0
  28. package/dist/common/recursiveQueryConfig.d.ts.map +1 -0
  29. package/dist/common/recursiveQueryConfig.js +129 -0
  30. package/dist/common/tableStructures.d.ts +176 -0
  31. package/dist/common/tableStructures.d.ts.map +1 -0
  32. package/dist/common/tableStructures.js +10 -0
  33. package/dist/common/types.d.ts +104 -0
  34. package/dist/common/types.d.ts.map +1 -0
  35. package/dist/common/types.js +31 -0
  36. package/dist/common/utils.d.ts +57 -0
  37. package/dist/common/utils.d.ts.map +1 -0
  38. package/dist/common/utils.js +300 -0
  39. package/dist/consumer/FileDownloadConsumer.d.ts +127 -0
  40. package/dist/consumer/FileDownloadConsumer.d.ts.map +1 -0
  41. package/dist/consumer/FileDownloadConsumer.js +1003 -0
  42. package/dist/consumer/generators/baseGenerator.d.ts +38 -0
  43. package/dist/consumer/generators/baseGenerator.d.ts.map +1 -0
  44. package/dist/consumer/generators/baseGenerator.js +103 -0
  45. package/dist/consumer/generators/domainGenerator.d.ts +78 -0
  46. package/dist/consumer/generators/domainGenerator.d.ts.map +1 -0
  47. package/dist/consumer/generators/domainGenerator.js +241 -0
  48. package/dist/consumer/generators/guiStatusGenerator.d.ts +16 -0
  49. package/dist/consumer/generators/guiStatusGenerator.d.ts.map +1 -0
  50. package/dist/consumer/generators/guiStatusGenerator.js +48 -0
  51. package/dist/consumer/generators/guiTitleGenerator.d.ts +16 -0
  52. package/dist/consumer/generators/guiTitleGenerator.d.ts.map +1 -0
  53. package/dist/consumer/generators/guiTitleGenerator.js +48 -0
  54. package/dist/consumer/generators/index.d.ts +14 -0
  55. package/dist/consumer/generators/index.d.ts.map +1 -0
  56. package/dist/consumer/generators/index.js +38 -0
  57. package/dist/consumer/generators/messageGenerator.d.ts +16 -0
  58. package/dist/consumer/generators/messageGenerator.d.ts.map +1 -0
  59. package/dist/consumer/generators/messageGenerator.js +73 -0
  60. package/dist/consumer/generators/metadataGenerator.d.ts +29 -0
  61. package/dist/consumer/generators/metadataGenerator.d.ts.map +1 -0
  62. package/dist/consumer/generators/metadataGenerator.js +135 -0
  63. package/dist/consumer/generators/screenGenerator.d.ts +173 -0
  64. package/dist/consumer/generators/screenGenerator.d.ts.map +1 -0
  65. package/dist/consumer/generators/screenGenerator.js +859 -0
  66. package/dist/consumer/generators/structureGenerator.d.ts +36 -0
  67. package/dist/consumer/generators/structureGenerator.d.ts.map +1 -0
  68. package/dist/consumer/generators/structureGenerator.js +131 -0
  69. package/dist/consumer/generators/textElementGenerator.d.ts +16 -0
  70. package/dist/consumer/generators/textElementGenerator.d.ts.map +1 -0
  71. package/dist/consumer/generators/textElementGenerator.js +70 -0
  72. package/dist/consumer/handlers/handleGetClass.d.ts +8 -0
  73. package/dist/consumer/handlers/handleGetClass.d.ts.map +1 -0
  74. package/dist/consumer/handlers/handleGetClass.js +18 -0
  75. package/dist/consumer/handlers/handleGetFunction.d.ts +8 -0
  76. package/dist/consumer/handlers/handleGetFunction.d.ts.map +1 -0
  77. package/dist/consumer/handlers/handleGetFunction.js +19 -0
  78. package/dist/consumer/handlers/handleGetFunctionGroup.d.ts +8 -0
  79. package/dist/consumer/handlers/handleGetFunctionGroup.d.ts.map +1 -0
  80. package/dist/consumer/handlers/handleGetFunctionGroup.js +19 -0
  81. package/dist/consumer/handlers/handleGetInclude.d.ts +8 -0
  82. package/dist/consumer/handlers/handleGetInclude.d.ts.map +1 -0
  83. package/dist/consumer/handlers/handleGetInclude.js +18 -0
  84. package/dist/consumer/handlers/handleGetProgram.d.ts +8 -0
  85. package/dist/consumer/handlers/handleGetProgram.d.ts.map +1 -0
  86. package/dist/consumer/handlers/handleGetProgram.js +27 -0
  87. package/dist/consumer/handlers/handleZTableQuery.d.ts +8 -0
  88. package/dist/consumer/handlers/handleZTableQuery.d.ts.map +1 -0
  89. package/dist/consumer/handlers/handleZTableQuery.js +20 -0
  90. package/dist/consumer/handlers/index.d.ts +10 -0
  91. package/dist/consumer/handlers/index.d.ts.map +1 -0
  92. package/dist/consumer/handlers/index.js +27 -0
  93. package/dist/consumer/index.d.ts +9 -0
  94. package/dist/consumer/index.d.ts.map +1 -0
  95. package/dist/consumer/index.js +24 -0
  96. package/dist/consumer/utils/download.d.ts +13 -0
  97. package/dist/consumer/utils/download.d.ts.map +1 -0
  98. package/dist/consumer/utils/download.js +38 -0
  99. package/dist/consumer/utils/index.d.ts +5 -0
  100. package/dist/consumer/utils/index.d.ts.map +1 -0
  101. package/dist/consumer/utils/index.js +20 -0
  102. package/dist/handlers/handleGetClass.d.ts +8 -0
  103. package/dist/handlers/handleGetClass.d.ts.map +1 -0
  104. package/dist/handlers/handleGetClass.js +19 -0
  105. package/dist/handlers/handleGetFunction.d.ts +8 -0
  106. package/dist/handlers/handleGetFunction.d.ts.map +1 -0
  107. package/dist/handlers/handleGetFunction.js +20 -0
  108. package/dist/handlers/handleGetFunctionGroup.d.ts +8 -0
  109. package/dist/handlers/handleGetFunctionGroup.d.ts.map +1 -0
  110. package/dist/handlers/handleGetFunctionGroup.js +19 -0
  111. package/dist/handlers/handleGetInclude.d.ts +8 -0
  112. package/dist/handlers/handleGetInclude.d.ts.map +1 -0
  113. package/dist/handlers/handleGetInclude.js +19 -0
  114. package/dist/handlers/handleGetInterface.d.ts +8 -0
  115. package/dist/handlers/handleGetInterface.d.ts.map +1 -0
  116. package/dist/handlers/handleGetInterface.js +19 -0
  117. package/dist/handlers/handleGetPackage.d.ts +8 -0
  118. package/dist/handlers/handleGetPackage.d.ts.map +1 -0
  119. package/dist/handlers/handleGetPackage.js +42 -0
  120. package/dist/handlers/handleGetProgram.d.ts +8 -0
  121. package/dist/handlers/handleGetProgram.d.ts.map +1 -0
  122. package/dist/handlers/handleGetProgram.js +19 -0
  123. package/dist/handlers/handleGetStructure.d.ts +8 -0
  124. package/dist/handlers/handleGetStructure.d.ts.map +1 -0
  125. package/dist/handlers/handleGetStructure.js +19 -0
  126. package/dist/handlers/handleGetTable.d.ts +8 -0
  127. package/dist/handlers/handleGetTable.d.ts.map +1 -0
  128. package/dist/handlers/handleGetTable.js +19 -0
  129. package/dist/handlers/handleGetTableContents.d.ts +8 -0
  130. package/dist/handlers/handleGetTableContents.d.ts.map +1 -0
  131. package/dist/handlers/handleGetTableContents.js +22 -0
  132. package/dist/handlers/handleGetTransaction.d.ts +8 -0
  133. package/dist/handlers/handleGetTransaction.d.ts.map +1 -0
  134. package/dist/handlers/handleGetTransaction.js +19 -0
  135. package/dist/handlers/handleGetTypeInfo.d.ts +8 -0
  136. package/dist/handlers/handleGetTypeInfo.d.ts.map +1 -0
  137. package/dist/handlers/handleGetTypeInfo.js +32 -0
  138. package/dist/handlers/handleSearchObject.d.ts +8 -0
  139. package/dist/handlers/handleSearchObject.d.ts.map +1 -0
  140. package/dist/handlers/handleSearchObject.js +20 -0
  141. package/dist/handlers/handleZObjectQuery.d.ts +8 -0
  142. package/dist/handlers/handleZObjectQuery.d.ts.map +1 -0
  143. package/dist/handlers/handleZObjectQuery.js +25 -0
  144. package/dist/handlers/handleZTableQuery.d.ts +8 -0
  145. package/dist/handlers/handleZTableQuery.d.ts.map +1 -0
  146. package/dist/handlers/handleZTableQuery.js +20 -0
  147. package/dist/index.d.ts +17 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +45 -0
  150. package/dist/lib/download.d.ts +49 -0
  151. package/dist/lib/download.d.ts.map +1 -0
  152. package/dist/lib/download.js +78 -0
  153. package/dist/lib/index.d.ts +9 -0
  154. package/dist/lib/index.d.ts.map +1 -0
  155. package/dist/lib/index.js +23 -0
  156. package/dist/lib/utils.d.ts +31 -0
  157. package/dist/lib/utils.d.ts.map +1 -0
  158. package/dist/lib/utils.js +272 -0
  159. package/dist/producer/RecursiveQueryProducer.d.ts +92 -0
  160. package/dist/producer/RecursiveQueryProducer.d.ts.map +1 -0
  161. package/dist/producer/RecursiveQueryProducer.js +496 -0
  162. package/dist/producer/handlers/handleZObjectQuery.d.ts +8 -0
  163. package/dist/producer/handlers/handleZObjectQuery.d.ts.map +1 -0
  164. package/dist/producer/handlers/handleZObjectQuery.js +24 -0
  165. package/dist/producer/handlers/index.d.ts +6 -0
  166. package/dist/producer/handlers/index.d.ts.map +1 -0
  167. package/dist/producer/handlers/index.js +21 -0
  168. package/dist/producer/index.d.ts +7 -0
  169. package/dist/producer/index.d.ts.map +1 -0
  170. package/dist/producer/index.js +22 -0
  171. package/dist/recursive/abapStructures.d.ts +377 -0
  172. package/dist/recursive/abapStructures.d.ts.map +1 -0
  173. package/dist/recursive/abapStructures.js +2 -0
  174. package/dist/recursive/generate/baseGenerator.d.ts +34 -0
  175. package/dist/recursive/generate/baseGenerator.d.ts.map +1 -0
  176. package/dist/recursive/generate/baseGenerator.js +112 -0
  177. package/dist/recursive/generate/domainGenerator.d.ts +26 -0
  178. package/dist/recursive/generate/domainGenerator.d.ts.map +1 -0
  179. package/dist/recursive/generate/domainGenerator.js +128 -0
  180. package/dist/recursive/generate/functionGroupGenerator.d.ts +30 -0
  181. package/dist/recursive/generate/functionGroupGenerator.d.ts.map +1 -0
  182. package/dist/recursive/generate/functionGroupGenerator.js +90 -0
  183. package/dist/recursive/generate/index.d.ts +12 -0
  184. package/dist/recursive/generate/index.d.ts.map +1 -0
  185. package/dist/recursive/generate/index.js +34 -0
  186. package/dist/recursive/generate/messageGenerator.d.ts +16 -0
  187. package/dist/recursive/generate/messageGenerator.d.ts.map +1 -0
  188. package/dist/recursive/generate/messageGenerator.js +73 -0
  189. package/dist/recursive/generate/screenGenerator.d.ts +173 -0
  190. package/dist/recursive/generate/screenGenerator.d.ts.map +1 -0
  191. package/dist/recursive/generate/screenGenerator.js +858 -0
  192. package/dist/recursive/generate/structureGenerator.d.ts +22 -0
  193. package/dist/recursive/generate/structureGenerator.d.ts.map +1 -0
  194. package/dist/recursive/generate/structureGenerator.js +88 -0
  195. package/dist/recursive/generate/textElementGenerator.d.ts +16 -0
  196. package/dist/recursive/generate/textElementGenerator.d.ts.map +1 -0
  197. package/dist/recursive/generate/textElementGenerator.js +68 -0
  198. package/dist/recursive/handleRecursiveObjectQuery.d.ts +94 -0
  199. package/dist/recursive/handleRecursiveObjectQuery.d.ts.map +1 -0
  200. package/dist/recursive/handleRecursiveObjectQuery.js +219 -0
  201. package/dist/recursive/recursiveObjectQuery.d.ts +159 -0
  202. package/dist/recursive/recursiveObjectQuery.d.ts.map +1 -0
  203. package/dist/recursive/recursiveObjectQuery.js +1358 -0
  204. package/dist/recursive/recursiveQueryConfig.d.ts +129 -0
  205. package/dist/recursive/recursiveQueryConfig.d.ts.map +1 -0
  206. package/dist/recursive/recursiveQueryConfig.js +133 -0
  207. package/dist/recursive/tableStructures.d.ts +196 -0
  208. package/dist/recursive/tableStructures.d.ts.map +1 -0
  209. package/dist/recursive/tableStructures.js +10 -0
  210. package/package.json +47 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-object.d.ts","sourceRoot":"","sources":["../../src/cli/query-object.ts"],"names":[],"mappings":""}
@@ -0,0 +1,486 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ // ⚠️ 重要:必须在所有其他导入之前加载环境变量
38
+ const dotenv = __importStar(require("dotenv"));
39
+ const path_1 = require("path");
40
+ const envPath = (0, path_1.join)(__dirname, '../../.env');
41
+ dotenv.config({ path: envPath });
42
+ // 加载环境变量后再导入其他模块(这些模块会读取 process.env)
43
+ const uuid_1 = require("uuid");
44
+ const common_1 = require("../common");
45
+ const producer_1 = require("../producer");
46
+ const consumer_1 = require("../consumer");
47
+ /**
48
+ * 命令行参数解析
49
+ */
50
+ function parseArgs() {
51
+ const args = process.argv.slice(2);
52
+ let queryType = '';
53
+ let queryName = '';
54
+ let maxDepth = 1;
55
+ let downloadIncludes = true;
56
+ let enableCircularCheck = true;
57
+ let concurrentLimit = 10;
58
+ let requestInterval = 100;
59
+ let downloadPath = './downloads';
60
+ let excludeNames = [];
61
+ let excludePatterns = [];
62
+ let jobId = undefined;
63
+ let organizeByProgram = true;
64
+ // 解析命令行参数
65
+ for (let i = 0; i < args.length; i++) {
66
+ const arg = args[i];
67
+ switch (arg) {
68
+ case '--type':
69
+ case '-t':
70
+ queryType = args[++i];
71
+ break;
72
+ case '--name':
73
+ case '-n':
74
+ queryName = args[++i];
75
+ break;
76
+ case '--exclude-name':
77
+ case '-e':
78
+ excludeNames.push(args[++i]);
79
+ break;
80
+ case '--exclude-pattern':
81
+ case '-x':
82
+ excludePatterns.push(args[++i]);
83
+ break;
84
+ case '--max-depth':
85
+ case '-d':
86
+ const depthValue = parseInt(args[++i]);
87
+ maxDepth = isNaN(depthValue) ? 1 : depthValue;
88
+ break;
89
+ case '--download-includes':
90
+ case '-i':
91
+ downloadIncludes = true;
92
+ break;
93
+ case '--no-circular-check':
94
+ enableCircularCheck = false;
95
+ break;
96
+ case '--concurrent-limit':
97
+ case '-c':
98
+ const concurrentValue = parseInt(args[++i]);
99
+ concurrentLimit = isNaN(concurrentValue) ? 10 : concurrentValue;
100
+ break;
101
+ case '--request-interval':
102
+ const intervalValue = parseInt(args[++i]);
103
+ requestInterval = isNaN(intervalValue) ? 100 : intervalValue;
104
+ break;
105
+ case '--download-path':
106
+ case '-p':
107
+ downloadPath = args[++i] || './downloads';
108
+ break;
109
+ case '--organize-by-program':
110
+ case '-o':
111
+ organizeByProgram = args[++i]?.toLowerCase() !== 'false';
112
+ break;
113
+ case '--job-id':
114
+ case '-j':
115
+ jobId = args[++i];
116
+ break;
117
+ case '--help':
118
+ case '-h':
119
+ showHelp();
120
+ process.exit(0);
121
+ break;
122
+ default:
123
+ if (!arg.startsWith('-') && !queryType) {
124
+ queryType = arg;
125
+ }
126
+ else if (!arg.startsWith('-') && !queryName) {
127
+ queryName = arg;
128
+ }
129
+ break;
130
+ }
131
+ }
132
+ if (!queryType || !queryName) {
133
+ console.error('错误:查询类型和查询名称都是必需的参数');
134
+ showHelp();
135
+ process.exit(1);
136
+ }
137
+ return {
138
+ queryType,
139
+ queryName,
140
+ maxDepth,
141
+ downloadIncludes,
142
+ enableCircularCheck,
143
+ concurrentLimit,
144
+ requestInterval,
145
+ downloadPath,
146
+ excludeNames,
147
+ excludePatterns,
148
+ jobId,
149
+ organizeByProgram
150
+ };
151
+ }
152
+ /**
153
+ * 显示帮助信息
154
+ */
155
+ function showHelp() {
156
+ console.error(`
157
+ SAP对象递归查询工具
158
+
159
+ 用法:
160
+ npm run query -- --type <查询类型> --name <查询名称> [选项]
161
+ npm run query -- -t <查询类型> -n <查询名称> [选项]
162
+ npm run query -- <查询类型> <查询名称> [选项]
163
+
164
+ 基本参数:
165
+ --type, -t 查询类型(必需)如:PROG, CLAS, FUGR, FUNC
166
+ --name, -n 查询名称(必需)
167
+ --help, -h 显示帮助信息
168
+
169
+ 递归配置:
170
+ --max-depth, -d 最大递归深度(默认:3)
171
+ --download-includes, -i 下载包含文件
172
+ --no-circular-check 禁用循环引用检测
173
+ --concurrent-limit, -c 并发请求限制(默认:10)
174
+ --request-interval 请求间隔时间(毫秒,默认:100)
175
+ --download-path, -p 下载路径(默认:./downloads)
176
+ --organize-by-program, -o 是否按程序分目录(默认:true)
177
+ true: downloads/PROGRAM_NAME/...
178
+ false: downloads/...
179
+ --job-id, -j 指定 Job ID(可选,不指定则自动生成)
180
+
181
+ 过滤配置(在默认规则基础上添加):
182
+ --exclude-name, -e 排除特定对象名称(精确匹配,可多次使用)
183
+ --exclude-pattern, -x 排除对象名称模式(支持通配符 * 和 ?,可多次使用)
184
+
185
+ 注:系统默认会过滤 SAP*、RS*、CL_GUI_*、CL_ABAP_* 等标准对象
186
+
187
+ 示例:
188
+ # 基本查询
189
+ npm run query -- --type PROG --name Z_MY_PROGRAM
190
+ npm run query -- -t CLAS -n ZCL_MY_CLASS
191
+ npm run query -- FUGR Z_MY_FUNCTION_GROUP
192
+
193
+ # 带深度和下载配置
194
+ npm run query -- -t CLAS -n ZCL_MY_CLASS -d 5 -i
195
+
196
+ # 不按程序分目录(所有文件在同一目录下)
197
+ npm run query -- -t PROG -n Z_MY_PROGRAM -o false
198
+
199
+ # 指定自定义 Job ID
200
+ npm run query -- -t PROG -n SAPLMEGUI -j my-custom-job-id
201
+
202
+ # 添加自定义过滤规则
203
+ npm run query -- -t PROG -n Z_MY_PROGRAM -e Z_OLD_PROGRAM -x "*_TEST"
204
+ npm run query -- -t CLAS -n ZCL_MY_CLASS -e Z_LEGACY -e Z_OBSOLETE -x "*_TMP" -x "TEMP_*"
205
+
206
+ # 完整示例
207
+ npm run query -- --type PROG --name Z_MY_PROGRAM \\
208
+ --max-depth 4 \\
209
+ --download-includes \\
210
+ --exclude-name Z_OLD_PROGRAM \\
211
+ --exclude-pattern "*_TEST" \\
212
+ --exclude-pattern "*_TMP"
213
+
214
+ 环境变量配置:
215
+ 需要在.env文件中配置以下变量:
216
+ - SAP_URL: SAP系统URL
217
+ - SAP_USERNAME: 用户名
218
+ - SAP_PASSWORD: 密码
219
+ - SAP_CLIENT: 客户端
220
+ `);
221
+ }
222
+ /**
223
+ * 格式化输出结果(递归查询)
224
+ */
225
+ function formatRecursiveOutput(result) {
226
+ if (!result.success) {
227
+ console.error('递归查询失败:', result.error);
228
+ process.exit(1);
229
+ }
230
+ try {
231
+ const data = result.data;
232
+ console.error('\n=== 递归查询结果 ===\n');
233
+ console.error(`✅ 查询成功: ${result.message}`);
234
+ console.error(`📊 统计信息:`);
235
+ console.error(` - 总对象数: ${data.statistics.totalObjects}`);
236
+ console.error(` - 总类数: ${data.statistics.totalClasses}`);
237
+ console.error(` - 总函数数: ${data.statistics.totalFunctions}`);
238
+ console.error(` - 总包含文件数: ${data.statistics.totalIncludes}`);
239
+ console.error(` - 最大深度: ${data.statistics.maxDepthReached}`);
240
+ console.error(` - 循环引用: ${data.statistics.circularReferences}`);
241
+ if (data.downloaded_files && data.downloaded_files.length > 0) {
242
+ // 分离成功和失败的文件
243
+ const successFiles = data.downloaded_files.filter((file) => file.success);
244
+ const failedFiles = data.downloaded_files.filter((file) => !file.success);
245
+ console.error(`💾 下载文件: ${data.downloaded_files.length}个 (成功: ${successFiles.length}, 失败: ${failedFiles.length})`);
246
+ // 成功的文件:超过20个只显示统计,否则显示详情
247
+ if (successFiles.length > 0) {
248
+ if (successFiles.length > 20) {
249
+ console.error(` ✅ 成功下载: ${successFiles.length}个文件 (列表省略)`);
250
+ }
251
+ else {
252
+ console.error(` ✅ 成功下载 (${successFiles.length}个):`);
253
+ successFiles.forEach((file, index) => {
254
+ console.error(` ${index + 1}. ${file.objectType}/${file.objectName}.abap`);
255
+ });
256
+ }
257
+ }
258
+ // 失败的文件:始终显示详情
259
+ if (failedFiles.length > 0) {
260
+ console.error(` ❌ 下载失败 (${failedFiles.length}个):`);
261
+ failedFiles.forEach((file, index) => {
262
+ const errorInfo = file.error ? ` - 错误: ${file.error}` : '';
263
+ console.error(` ${index + 1}. ${file.objectType}/${file.objectName}.abap${errorInfo}`);
264
+ });
265
+ }
266
+ }
267
+ // 只在对象数量较少或需要详细信息时输出对象列表
268
+ if (data.all_objects.length <= 20) {
269
+ console.error(`🔍 发现的对象 (${data.all_objects.length}个):`);
270
+ data.all_objects.forEach((obj, index) => {
271
+ const objectKey = obj.object_key;
272
+ const objectData = obj.object_data;
273
+ console.error(` ${index + 1}. ${objectKey}`);
274
+ // 显示关键信息
275
+ if (objectData.FUNCTIONNAME) {
276
+ console.error(` 函数: ${objectData.FUNCTIONNAME} - ${objectData.FUNCTIONTITLE || '无标题'}`);
277
+ }
278
+ else if (objectData.CLASSNAME) {
279
+ console.error(` 类: ${objectData.CLASSNAME} - ${objectData.DESCRIPTION || '无描述'}`);
280
+ }
281
+ else if (objectData.TABNAME) {
282
+ console.error(` 表: ${objectData.TABNAME}`);
283
+ }
284
+ });
285
+ }
286
+ else {
287
+ console.error(`🔍 发现的对象: ${data.all_objects.length}个 (数量较多,省略详细列表)`);
288
+ }
289
+ // 显示被过滤的对象
290
+ if (data.filtered_objects && data.filtered_objects.length > 0) {
291
+ console.error(`\n🚫 被过滤的对象 (${data.filtered_objects.length}个,未进行递归查询):`);
292
+ // 统计
293
+ const exactFiltered = data.filtered_objects.filter((obj) => obj.filterType === 'exact');
294
+ const patternFiltered = data.filtered_objects.filter((obj) => obj.filterType === 'pattern');
295
+ console.error(` 📌 精确匹配: ${exactFiltered.length}个`);
296
+ console.error(` 🔍 模式匹配: ${patternFiltered.length}个`);
297
+ // 显示详情(最多显示前20个)
298
+ const displayCount = Math.min(data.filtered_objects.length, 20);
299
+ if (displayCount < data.filtered_objects.length) {
300
+ console.error(` (仅显示前${displayCount}个,共${data.filtered_objects.length}个)`);
301
+ }
302
+ data.filtered_objects.slice(0, displayCount).forEach((obj, index) => {
303
+ const icon = obj.filterType === 'exact' ? '📌' : '🔍';
304
+ const ruleInfo = obj.filterRule ? ` [规则: ${obj.filterRule}]` : '';
305
+ console.error(` ${icon} ${index + 1}. ${obj.objectType}:${obj.objectName}${ruleInfo}`);
306
+ });
307
+ }
308
+ if (data.errors && data.errors.length > 0) {
309
+ console.error(`\n⚠️ 错误 (${data.errors.length}个):`);
310
+ data.errors.forEach((error, index) => {
311
+ console.error(` ${index + 1}. ${error}`);
312
+ });
313
+ }
314
+ console.error(`\n📝 ${data.summary}`);
315
+ }
316
+ catch (error) {
317
+ console.error('格式化输出失败:', error);
318
+ console.error('原始数据:', JSON.stringify(result, null, 2));
319
+ }
320
+ }
321
+ /**
322
+ * 执行递归查询(使用 Redis 队列系统)
323
+ */
324
+ async function executeRecursiveQuery(objectType, objectName, config, consumerCount = 10, jobId, organizeByProgram = true) {
325
+ console.error(`[Queue] 开始递归查询 - 类型: ${objectType}, 名称: ${objectName}`);
326
+ // 1. 创建 RedisQueueManager
327
+ const queueManager = new common_1.RedisQueueManager();
328
+ // 2. 创建生产者
329
+ const producer = new producer_1.RecursiveQueryProducer(queueManager);
330
+ // 3. 准备消费者
331
+ const consumers = [];
332
+ console.error(`[Queue] 启动 ${consumerCount} 个消费者...`);
333
+ try {
334
+ // 4. 创建 Job(使用指定的 jobId 或生成新的)
335
+ const finalJobId = jobId || (0, uuid_1.v4)();
336
+ if (jobId) {
337
+ console.error(`[Queue] 使用指定的 Job ID: ${finalJobId}`);
338
+ }
339
+ else {
340
+ console.error(`[Queue] 生成的 Job ID: ${finalJobId}`);
341
+ }
342
+ await producer.createJob(finalJobId, objectType, objectName, config);
343
+ console.error(`[Queue] Job 已创建: ${finalJobId}`);
344
+ // 5. 启动消费者(立即开始监听队列)
345
+ console.error(`[Queue] 启动 ${consumerCount} 个消费者(与生产者并行)...`);
346
+ const consumerPromises = [];
347
+ for (let i = 0; i < consumerCount; i++) {
348
+ const consumer = new consumer_1.FileDownloadConsumer(queueManager, config.downloadRootPath, [finalJobId], organizeByProgram);
349
+ consumers.push(consumer);
350
+ consumerPromises.push(consumer.start([finalJobId]).catch(err => {
351
+ console.error(`[Queue] 消费者 ${i + 1} 错误:`, err);
352
+ }));
353
+ }
354
+ // 6. 启动生产者递归查询(虽然会阻塞,但消费者已经在并行工作)
355
+ console.error(`[Queue] 生产者开始递归查询(消费者已在监听)...`);
356
+ await producer.generateAllTasks(finalJobId, objectType, objectName, config);
357
+ console.error(`[Queue] 生产者任务生成完成`);
358
+ // 7. 等待消费者处理完所有任务
359
+ console.error(`[Queue] 等待消费者处理剩余任务...`);
360
+ const job = await producer.waitForCompletion(finalJobId);
361
+ // 8. 停止所有消费者
362
+ console.error(`[Queue] 停止消费者...`);
363
+ for (const consumer of consumers) {
364
+ await consumer.stop();
365
+ }
366
+ await Promise.allSettled(consumerPromises);
367
+ // 9. 收集结果
368
+ const downloadedFiles = [];
369
+ for (const consumer of consumers) {
370
+ downloadedFiles.push(...consumer.getDownloadedFiles());
371
+ }
372
+ // 10. 生成统计信息
373
+ const statistics = {
374
+ totalObjects: job.totalTasks,
375
+ totalTasks: job.totalTasks,
376
+ completedTasks: job.completedTasks,
377
+ failedTasks: job.failedTasks,
378
+ skippedTasks: job.skippedTasks,
379
+ totalFiles: downloadedFiles.length,
380
+ successFiles: downloadedFiles.filter(f => f.success).length,
381
+ failedFiles: downloadedFiles.filter(f => !f.success).length,
382
+ totalClasses: 0,
383
+ totalFunctions: 0,
384
+ totalPrograms: 0,
385
+ totalIncludes: 0,
386
+ totalStructures: 0,
387
+ totalDomains: 0,
388
+ downloadedIncludes: 0,
389
+ downloadedStructures: 0,
390
+ downloadedDomains: 0,
391
+ maxDepthReached: config.maxRecursionDepth || 1,
392
+ circularReferences: 0
393
+ };
394
+ console.error(`[Queue] 递归查询完成`);
395
+ console.error(`[Queue] 统计: ${JSON.stringify(statistics, null, 2)}`);
396
+ // 11. 清理
397
+ await queueManager.cleanupJob(finalJobId);
398
+ await queueManager.close();
399
+ // 12. 返回结果
400
+ return {
401
+ success: true,
402
+ data: {
403
+ jobId: finalJobId,
404
+ original_object: null,
405
+ all_objects: [],
406
+ downloaded_files: downloadedFiles,
407
+ filtered_objects: [],
408
+ statistics,
409
+ errors: job.errors || [],
410
+ summary: `Job ${finalJobId} 完成 - 状态: ${job.status}, 完成任务: ${job.completedTasks}/${job.totalTasks}`
411
+ },
412
+ message: `递归查询完成 - 处理了 ${job.totalTasks} 个对象`
413
+ };
414
+ }
415
+ finally {
416
+ // 确保所有消费者都停止
417
+ for (const consumer of consumers) {
418
+ await consumer.stop();
419
+ }
420
+ }
421
+ }
422
+ /**
423
+ * 主函数
424
+ */
425
+ async function main() {
426
+ console.error('SAP对象查询工具\n');
427
+ // 检查环境变量
428
+ const requiredEnvVars = ['SAP_URL', 'SAP_USERNAME', 'SAP_PASSWORD', 'SAP_CLIENT'];
429
+ const missingEnvVars = requiredEnvVars.filter(varName => !process.env[varName]);
430
+ if (missingEnvVars.length > 0) {
431
+ console.error('错误:缺少必需的环境变量:', missingEnvVars.join(', '));
432
+ console.error('请在.env文件中配置这些变量');
433
+ process.exit(1);
434
+ }
435
+ try {
436
+ const args = parseArgs();
437
+ console.error(`正在执行递归查询 ${args.queryType} 对象: ${args.queryName}...`);
438
+ console.error(`配置: 最大深度=${args.maxDepth}, 并发限制=${args.concurrentLimit}`);
439
+ if (args.downloadPath) {
440
+ console.error(`下载路径: ${args.downloadPath}`);
441
+ }
442
+ // 显示过滤配置
443
+ if (args.excludeNames && args.excludeNames.length > 0) {
444
+ console.error(`自定义过滤(精确匹配): ${args.excludeNames.join(', ')}`);
445
+ }
446
+ if (args.excludePatterns && args.excludePatterns.length > 0) {
447
+ console.error(`自定义过滤(模式匹配): ${args.excludePatterns.join(', ')}`);
448
+ }
449
+ // 构建过滤配置
450
+ const recursionFilters = {};
451
+ if (args.excludeNames && args.excludeNames.length > 0) {
452
+ recursionFilters.excludeNames = args.excludeNames;
453
+ }
454
+ if (args.excludePatterns && args.excludePatterns.length > 0) {
455
+ recursionFilters.excludeNamePatterns = args.excludePatterns;
456
+ }
457
+ // 构建配置
458
+ const config = {
459
+ maxRecursionDepth: args.maxDepth,
460
+ downloadRootPath: args.downloadPath,
461
+ downloadIncludes: args.downloadIncludes,
462
+ enableCircularReferenceCheck: args.enableCircularCheck,
463
+ concurrentRequestLimit: args.concurrentLimit,
464
+ requestInterval: args.requestInterval,
465
+ recursionFilters: Object.keys(recursionFilters).length > 0 ? recursionFilters : undefined
466
+ };
467
+ console.error(`\n[Queue] 配置: ${JSON.stringify(config, null, 2)}`);
468
+ // 执行递归查询(使用队列系统)
469
+ const result = await executeRecursiveQuery(args.queryType.toUpperCase(), args.queryName.toUpperCase(), config, 10, // 默认10个消费者
470
+ args.jobId, // 传入 jobId(可选)
471
+ args.organizeByProgram // 是否按程序分目录
472
+ );
473
+ formatRecursiveOutput(result);
474
+ }
475
+ catch (error) {
476
+ console.error('执行失败:', error instanceof Error ? error.message : String(error));
477
+ process.exit(1);
478
+ }
479
+ }
480
+ // 运行主函数
481
+ if (require.main === module) {
482
+ main().catch(error => {
483
+ console.error('未捕获的错误:', error);
484
+ process.exit(1);
485
+ });
486
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * 过滤规则缓存
3
+ * 预编译正则表达式,避免每次检查时重复编译
4
+ *
5
+ * 性能优化:
6
+ * - 预编译所有模式为正则表达式(一次性开销)
7
+ * - 缓存编译结果,避免重复编译
8
+ * - 支持通配符:* 匹配任意字符,? 匹配单个字符
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const cache = new FilterCache(['SAP*', 'CL_?_TEST']);
13
+ * cache.matches('SAPLMEGUI'); // true (匹配 SAP*)
14
+ * cache.matches('CL_A_TEST'); // true (匹配 CL_?_TEST)
15
+ * cache.matches('MY_PROG'); // false
16
+ * ```
17
+ */
18
+ export declare class FilterCache {
19
+ private compiledPatterns;
20
+ private exactMatches;
21
+ /**
22
+ * 构造函数
23
+ * @param exactNames 精确匹配的名称列表
24
+ * @param patterns 通配符模式列表
25
+ */
26
+ constructor(exactNames?: string[], patterns?: string[]);
27
+ /**
28
+ * 检查名称是否匹配任何过滤规则
29
+ * @param objectName 对象名称
30
+ * @returns true 表示匹配(应该过滤),false 表示不匹配
31
+ */
32
+ matches(objectName: string): boolean;
33
+ /**
34
+ * 获取匹配的模式(用于调试)
35
+ * @param objectName 对象名称
36
+ * @returns 匹配的模式列表
37
+ */
38
+ getMatchedPatterns(objectName: string): string[];
39
+ /**
40
+ * 将通配符模式转换为正则表达式
41
+ * @param pattern 通配符模式(支持 * 和 ?)
42
+ * @returns 正则表达式字符串
43
+ *
44
+ * @example
45
+ * SAP* -> ^SAP.*$
46
+ * CL_?_TEST -> ^CL_.\_TEST$
47
+ * *_TEMP -> ^.*_TEMP$
48
+ */
49
+ private convertPatternToRegex;
50
+ /**
51
+ * 获取统计信息
52
+ */
53
+ getStats(): {
54
+ exactMatchCount: number;
55
+ patternCount: number;
56
+ };
57
+ /**
58
+ * 清空缓存
59
+ */
60
+ clear(): void;
61
+ }
62
+ //# sourceMappingURL=FilterCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterCache.d.ts","sourceRoot":"","sources":["../../src/common/FilterCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,gBAAgB,CAGhB;IAER,OAAO,CAAC,YAAY,CAA0B;IAE9C;;;;OAIG;gBACS,UAAU,GAAE,MAAM,EAAO,EAAE,QAAQ,GAAE,MAAM,EAAO;IAgB9D;;;;OAIG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAkBpC;;;;OAIG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAmBhD;;;;;;;;;OASG;IACH,OAAO,CAAC,qBAAqB;IAa7B;;OAEG;IACH,QAAQ,IAAI;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;IAO7D;;OAEG;IACH,KAAK,IAAI,IAAI;CAIhB"}
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FilterCache = void 0;
4
+ /**
5
+ * 过滤规则缓存
6
+ * 预编译正则表达式,避免每次检查时重复编译
7
+ *
8
+ * 性能优化:
9
+ * - 预编译所有模式为正则表达式(一次性开销)
10
+ * - 缓存编译结果,避免重复编译
11
+ * - 支持通配符:* 匹配任意字符,? 匹配单个字符
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const cache = new FilterCache(['SAP*', 'CL_?_TEST']);
16
+ * cache.matches('SAPLMEGUI'); // true (匹配 SAP*)
17
+ * cache.matches('CL_A_TEST'); // true (匹配 CL_?_TEST)
18
+ * cache.matches('MY_PROG'); // false
19
+ * ```
20
+ */
21
+ class FilterCache {
22
+ compiledPatterns = [];
23
+ exactMatches = new Set(); // 精确匹配集合(O(1)查找)
24
+ /**
25
+ * 构造函数
26
+ * @param exactNames 精确匹配的名称列表
27
+ * @param patterns 通配符模式列表
28
+ */
29
+ constructor(exactNames = [], patterns = []) {
30
+ // 1. 构建精确匹配集合(O(1)查找)
31
+ exactNames.forEach(name => {
32
+ this.exactMatches.add(name.toUpperCase());
33
+ });
34
+ // 2. 预编译所有模式为正则表达式
35
+ this.compiledPatterns = patterns.map(pattern => {
36
+ const regexPattern = this.convertPatternToRegex(pattern);
37
+ return {
38
+ pattern,
39
+ regex: new RegExp(regexPattern, 'i') // 不区分大小写
40
+ };
41
+ });
42
+ }
43
+ /**
44
+ * 检查名称是否匹配任何过滤规则
45
+ * @param objectName 对象名称
46
+ * @returns true 表示匹配(应该过滤),false 表示不匹配
47
+ */
48
+ matches(objectName) {
49
+ const upperName = objectName.toUpperCase();
50
+ // 1. 快速路径:精确匹配检查(O(1))
51
+ if (this.exactMatches.has(upperName)) {
52
+ return true;
53
+ }
54
+ // 2. 模式匹配检查(使用预编译的正则表达式)
55
+ for (const { regex } of this.compiledPatterns) {
56
+ if (regex.test(objectName)) {
57
+ return true;
58
+ }
59
+ }
60
+ return false;
61
+ }
62
+ /**
63
+ * 获取匹配的模式(用于调试)
64
+ * @param objectName 对象名称
65
+ * @returns 匹配的模式列表
66
+ */
67
+ getMatchedPatterns(objectName) {
68
+ const matched = [];
69
+ const upperName = objectName.toUpperCase();
70
+ // 检查精确匹配
71
+ if (this.exactMatches.has(upperName)) {
72
+ matched.push(`[精确匹配] ${upperName}`);
73
+ }
74
+ // 检查模式匹配
75
+ for (const { pattern, regex } of this.compiledPatterns) {
76
+ if (regex.test(objectName)) {
77
+ matched.push(`[模式匹配] ${pattern}`);
78
+ }
79
+ }
80
+ return matched;
81
+ }
82
+ /**
83
+ * 将通配符模式转换为正则表达式
84
+ * @param pattern 通配符模式(支持 * 和 ?)
85
+ * @returns 正则表达式字符串
86
+ *
87
+ * @example
88
+ * SAP* -> ^SAP.*$
89
+ * CL_?_TEST -> ^CL_.\_TEST$
90
+ * *_TEMP -> ^.*_TEMP$
91
+ */
92
+ convertPatternToRegex(pattern) {
93
+ // 1. 转义特殊字符(除了 * 和 ?)
94
+ let regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&');
95
+ // 2. 转换通配符
96
+ regexPattern = regexPattern
97
+ .replace(/\*/g, '.*') // * -> .* (匹配任意字符)
98
+ .replace(/\?/g, '.'); // ? -> . (匹配单个字符)
99
+ // 3. 添加锚点(确保完全匹配)
100
+ return `^${regexPattern}$`;
101
+ }
102
+ /**
103
+ * 获取统计信息
104
+ */
105
+ getStats() {
106
+ return {
107
+ exactMatchCount: this.exactMatches.size,
108
+ patternCount: this.compiledPatterns.length
109
+ };
110
+ }
111
+ /**
112
+ * 清空缓存
113
+ */
114
+ clear() {
115
+ this.exactMatches.clear();
116
+ this.compiledPatterns = [];
117
+ }
118
+ }
119
+ exports.FilterCache = FilterCache;