@peernova/cuneiform-sf 1.0.2 → 1.0.4-beta.8

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 (494) hide show
  1. package/LICENSE +81 -30
  2. package/README.md +59 -95
  3. package/lib/adapters/connection-facade.d.ts +458 -0
  4. package/lib/adapters/connection-facade.js +379 -0
  5. package/lib/adapters/connection-facade.js.map +1 -0
  6. package/lib/adapters/errors.d.ts +547 -0
  7. package/lib/adapters/errors.js +937 -0
  8. package/lib/adapters/errors.js.map +1 -0
  9. package/lib/adapters/index.d.ts +33 -0
  10. package/lib/adapters/index.js +50 -0
  11. package/lib/adapters/index.js.map +1 -0
  12. package/lib/adapters/lifecycle.d.ts +119 -0
  13. package/lib/adapters/lifecycle.js +94 -0
  14. package/lib/adapters/lifecycle.js.map +1 -0
  15. package/lib/adapters/rest/cache.d.ts +69 -0
  16. package/lib/adapters/rest/cache.js +133 -0
  17. package/lib/adapters/rest/cache.js.map +1 -0
  18. package/lib/adapters/rest/index.d.ts +11 -0
  19. package/lib/adapters/rest/index.js +18 -0
  20. package/lib/adapters/rest/index.js.map +1 -0
  21. package/lib/adapters/rest/profiling-rest-client.d.ts +137 -0
  22. package/lib/adapters/rest/profiling-rest-client.js +115 -0
  23. package/lib/adapters/rest/profiling-rest-client.js.map +1 -0
  24. package/lib/adapters/rest/rest-api-adapter.d.ts +389 -0
  25. package/lib/adapters/rest/rest-api-adapter.js +747 -0
  26. package/lib/adapters/rest/rest-api-adapter.js.map +1 -0
  27. package/lib/adapters/rest/types.d.ts +34 -0
  28. package/lib/adapters/rest/types.js +9 -0
  29. package/lib/adapters/rest/types.js.map +1 -0
  30. package/lib/adapters/retry.d.ts +91 -0
  31. package/lib/adapters/retry.js +215 -0
  32. package/lib/adapters/retry.js.map +1 -0
  33. package/lib/adapters/soql/cuneiform-query-builder.d.ts +391 -0
  34. package/lib/adapters/soql/cuneiform-query-builder.js +559 -0
  35. package/lib/adapters/soql/cuneiform-query-builder.js.map +1 -0
  36. package/lib/adapters/soql/index.d.ts +13 -0
  37. package/lib/adapters/soql/index.js +21 -0
  38. package/lib/adapters/soql/index.js.map +1 -0
  39. package/lib/adapters/soql/soql-query-adapter.d.ts +141 -0
  40. package/lib/adapters/soql/soql-query-adapter.js +259 -0
  41. package/lib/adapters/soql/soql-query-adapter.js.map +1 -0
  42. package/lib/adapters/soql/types.d.ts +37 -0
  43. package/lib/adapters/soql/types.js +19 -0
  44. package/lib/adapters/soql/types.js.map +1 -0
  45. package/lib/adapters/testing/index.d.ts +37 -0
  46. package/lib/adapters/testing/index.js +20 -0
  47. package/lib/adapters/testing/index.js.map +1 -0
  48. package/lib/adapters/testing/mock-connection.d.ts +77 -0
  49. package/lib/adapters/testing/mock-connection.js +207 -0
  50. package/lib/adapters/testing/mock-connection.js.map +1 -0
  51. package/lib/adapters/testing/mock-logger.d.ts +29 -0
  52. package/lib/adapters/testing/mock-logger.js +57 -0
  53. package/lib/adapters/testing/mock-logger.js.map +1 -0
  54. package/lib/adapters/testing/mock-mcp-adapters.d.ts +32 -0
  55. package/lib/adapters/testing/mock-mcp-adapters.js +52 -0
  56. package/lib/adapters/testing/mock-mcp-adapters.js.map +1 -0
  57. package/lib/adapters/testing/mock-oclif-config.d.ts +22 -0
  58. package/lib/adapters/testing/mock-oclif-config.js +90 -0
  59. package/lib/adapters/testing/mock-oclif-config.js.map +1 -0
  60. package/lib/adapters/testing/mock-rest-adapter.d.ts +26 -0
  61. package/lib/adapters/testing/mock-rest-adapter.js +243 -0
  62. package/lib/adapters/testing/mock-rest-adapter.js.map +1 -0
  63. package/lib/adapters/testing/mock-salesforce-connection.d.ts +40 -0
  64. package/lib/adapters/testing/mock-salesforce-connection.js +61 -0
  65. package/lib/adapters/testing/mock-salesforce-connection.js.map +1 -0
  66. package/lib/adapters/testing/mock-soql-adapter.d.ts +30 -0
  67. package/lib/adapters/testing/mock-soql-adapter.js +120 -0
  68. package/lib/adapters/testing/mock-soql-adapter.js.map +1 -0
  69. package/lib/adapters/testing/mock-tooling-adapter.d.ts +24 -0
  70. package/lib/adapters/testing/mock-tooling-adapter.js +163 -0
  71. package/lib/adapters/testing/mock-tooling-adapter.js.map +1 -0
  72. package/lib/adapters/testing/stub-connection.d.ts +93 -0
  73. package/lib/adapters/testing/stub-connection.js +97 -0
  74. package/lib/adapters/testing/stub-connection.js.map +1 -0
  75. package/lib/adapters/testing/stub-rest-adapter.d.ts +52 -0
  76. package/lib/adapters/testing/stub-rest-adapter.js +58 -0
  77. package/lib/adapters/testing/stub-rest-adapter.js.map +1 -0
  78. package/lib/adapters/testing/stub-soql-adapter.d.ts +56 -0
  79. package/lib/adapters/testing/stub-soql-adapter.js +50 -0
  80. package/lib/adapters/testing/stub-soql-adapter.js.map +1 -0
  81. package/lib/adapters/testing/types.d.ts +71 -0
  82. package/lib/adapters/testing/types.js +9 -0
  83. package/lib/adapters/testing/types.js.map +1 -0
  84. package/lib/adapters/tooling/index.d.ts +10 -0
  85. package/lib/adapters/tooling/index.js +17 -0
  86. package/lib/adapters/tooling/index.js.map +1 -0
  87. package/lib/adapters/tooling/tooling-api-adapter.d.ts +157 -0
  88. package/lib/adapters/tooling/tooling-api-adapter.js +339 -0
  89. package/lib/adapters/tooling/tooling-api-adapter.js.map +1 -0
  90. package/lib/adapters/tooling/types.d.ts +81 -0
  91. package/lib/adapters/tooling/types.js +9 -0
  92. package/lib/adapters/tooling/types.js.map +1 -0
  93. package/lib/adapters/types.d.ts +112 -0
  94. package/lib/adapters/types.js +169 -0
  95. package/lib/adapters/types.js.map +1 -0
  96. package/lib/base/cuneiform-command.d.ts +152 -0
  97. package/lib/base/cuneiform-command.js +243 -0
  98. package/lib/base/cuneiform-command.js.map +1 -0
  99. package/lib/commands/cuneiform/compatibility/check.d.ts +43 -0
  100. package/lib/commands/cuneiform/compatibility/check.js +114 -0
  101. package/lib/commands/cuneiform/compatibility/check.js.map +1 -0
  102. package/lib/commands/cuneiform/definition/create.d.ts +119 -0
  103. package/lib/commands/cuneiform/definition/create.js +693 -0
  104. package/lib/commands/cuneiform/definition/create.js.map +1 -0
  105. package/lib/commands/cuneiform/definition/export.d.ts +57 -0
  106. package/lib/commands/cuneiform/definition/export.js +133 -0
  107. package/lib/commands/cuneiform/definition/export.js.map +1 -0
  108. package/lib/commands/cuneiform/definition/get.d.ts +86 -0
  109. package/lib/commands/cuneiform/definition/get.js +270 -0
  110. package/lib/commands/cuneiform/definition/get.js.map +1 -0
  111. package/lib/commands/cuneiform/definition/import.d.ts +54 -0
  112. package/lib/commands/cuneiform/definition/import.js +118 -0
  113. package/lib/commands/cuneiform/definition/import.js.map +1 -0
  114. package/lib/commands/cuneiform/definition/list.d.ts +110 -0
  115. package/lib/commands/cuneiform/definition/list.js +344 -0
  116. package/lib/commands/cuneiform/definition/list.js.map +1 -0
  117. package/lib/commands/cuneiform/definition/purge.d.ts +105 -0
  118. package/lib/commands/cuneiform/definition/purge.js +533 -0
  119. package/lib/commands/cuneiform/definition/purge.js.map +1 -0
  120. package/lib/commands/cuneiform/definition/update.d.ts +58 -0
  121. package/lib/commands/cuneiform/definition/update.js +206 -0
  122. package/lib/commands/cuneiform/definition/update.js.map +1 -0
  123. package/lib/commands/cuneiform/mcp/serve.d.ts +56 -0
  124. package/lib/commands/cuneiform/mcp/serve.js +109 -0
  125. package/lib/commands/cuneiform/mcp/serve.js.map +1 -0
  126. package/lib/commands/cuneiform/object/describe.d.ts +61 -0
  127. package/lib/commands/cuneiform/object/describe.js +461 -0
  128. package/lib/commands/cuneiform/object/describe.js.map +1 -0
  129. package/lib/commands/cuneiform/object/list.d.ts +111 -0
  130. package/lib/commands/cuneiform/object/list.js +239 -0
  131. package/lib/commands/cuneiform/object/list.js.map +1 -0
  132. package/lib/commands/cuneiform/org/details.d.ts +99 -0
  133. package/lib/commands/cuneiform/org/details.js +521 -0
  134. package/lib/commands/cuneiform/org/details.js.map +1 -0
  135. package/lib/commands/cuneiform/org/reset.d.ts +46 -0
  136. package/lib/commands/cuneiform/org/reset.js +135 -0
  137. package/lib/commands/cuneiform/org/reset.js.map +1 -0
  138. package/lib/commands/cuneiform/profile/request/cancel.d.ts +59 -0
  139. package/lib/commands/cuneiform/profile/request/cancel.js +202 -0
  140. package/lib/commands/cuneiform/profile/request/cancel.js.map +1 -0
  141. package/lib/commands/cuneiform/profile/request/delete.d.ts +59 -0
  142. package/lib/commands/cuneiform/profile/request/delete.js +223 -0
  143. package/lib/commands/cuneiform/profile/request/delete.js.map +1 -0
  144. package/lib/commands/cuneiform/profile/request/list.d.ts +35 -0
  145. package/lib/commands/cuneiform/profile/request/list.js +102 -0
  146. package/lib/commands/cuneiform/profile/request/list.js.map +1 -0
  147. package/lib/commands/cuneiform/profile.d.ts +90 -0
  148. package/lib/commands/cuneiform/profile.js +322 -0
  149. package/lib/commands/cuneiform/profile.js.map +1 -0
  150. package/lib/commands/cuneiform/summary/purge.d.ts +77 -0
  151. package/lib/commands/cuneiform/summary/purge.js +429 -0
  152. package/lib/commands/cuneiform/summary/purge.js.map +1 -0
  153. package/lib/commands/cuneiform/summary/reprofile.d.ts +60 -0
  154. package/lib/commands/cuneiform/summary/reprofile.js +236 -0
  155. package/lib/commands/cuneiform/summary/reprofile.js.map +1 -0
  156. package/lib/commands/cuneiform/summary/stop.d.ts +59 -0
  157. package/lib/commands/cuneiform/summary/stop.js +234 -0
  158. package/lib/commands/cuneiform/summary/stop.js.map +1 -0
  159. package/lib/commands/cuneiform/user/details.d.ts +73 -0
  160. package/lib/commands/cuneiform/user/details.js +391 -0
  161. package/lib/commands/cuneiform/user/details.js.map +1 -0
  162. package/lib/constants/index.d.ts +8 -0
  163. package/lib/constants/index.js +16 -0
  164. package/lib/constants/index.js.map +1 -0
  165. package/lib/constants/namespace-constants.d.ts +91 -0
  166. package/lib/constants/namespace-constants.js +211 -0
  167. package/lib/constants/namespace-constants.js.map +1 -0
  168. package/lib/debug/command-debug-proxy.d.ts +101 -0
  169. package/lib/debug/command-debug-proxy.js +171 -0
  170. package/lib/debug/command-debug-proxy.js.map +1 -0
  171. package/lib/debug/debug-logger.d.ts +85 -0
  172. package/lib/debug/debug-logger.js +133 -0
  173. package/lib/debug/debug-logger.js.map +1 -0
  174. package/lib/debug/index.d.ts +12 -0
  175. package/lib/debug/index.js +20 -0
  176. package/lib/debug/index.js.map +1 -0
  177. package/lib/debug/service-debug-proxy.d.ts +30 -0
  178. package/lib/debug/service-debug-proxy.js +102 -0
  179. package/lib/debug/service-debug-proxy.js.map +1 -0
  180. package/lib/hooks/prerun.d.ts +25 -0
  181. package/lib/hooks/prerun.js +47 -0
  182. package/lib/hooks/prerun.js.map +1 -0
  183. package/lib/mcp/config/mcp-config.d.ts +55 -0
  184. package/lib/mcp/config/mcp-config.js +51 -0
  185. package/lib/mcp/config/mcp-config.js.map +1 -0
  186. package/lib/mcp/config/pagination.d.ts +96 -0
  187. package/lib/mcp/config/pagination.js +108 -0
  188. package/lib/mcp/config/pagination.js.map +1 -0
  189. package/lib/mcp/config/system-prompts.d.ts +18 -0
  190. package/lib/mcp/config/system-prompts.js +92 -0
  191. package/lib/mcp/config/system-prompts.js.map +1 -0
  192. package/lib/mcp/errors.d.ts +23 -0
  193. package/lib/mcp/errors.js +27 -0
  194. package/lib/mcp/errors.js.map +1 -0
  195. package/lib/mcp/schemas/input-schemas.d.ts +327 -0
  196. package/lib/mcp/schemas/input-schemas.js +302 -0
  197. package/lib/mcp/schemas/input-schemas.js.map +1 -0
  198. package/lib/mcp/server.d.ts +40 -0
  199. package/lib/mcp/server.js +316 -0
  200. package/lib/mcp/server.js.map +1 -0
  201. package/lib/mcp/tools/contactpoint-tools.d.ts +14 -0
  202. package/lib/mcp/tools/contactpoint-tools.js +34 -0
  203. package/lib/mcp/tools/contactpoint-tools.js.map +1 -0
  204. package/lib/mcp/tools/definition-io-tools.d.ts +19 -0
  205. package/lib/mcp/tools/definition-io-tools.js +152 -0
  206. package/lib/mcp/tools/definition-io-tools.js.map +1 -0
  207. package/lib/mcp/tools/definition-tools.d.ts +51 -0
  208. package/lib/mcp/tools/definition-tools.js +199 -0
  209. package/lib/mcp/tools/definition-tools.js.map +1 -0
  210. package/lib/mcp/tools/index.d.ts +37 -0
  211. package/lib/mcp/tools/index.js +88 -0
  212. package/lib/mcp/tools/index.js.map +1 -0
  213. package/lib/mcp/tools/object-tools.d.ts +22 -0
  214. package/lib/mcp/tools/object-tools.js +306 -0
  215. package/lib/mcp/tools/object-tools.js.map +1 -0
  216. package/lib/mcp/tools/org-tools.d.ts +14 -0
  217. package/lib/mcp/tools/org-tools.js +177 -0
  218. package/lib/mcp/tools/org-tools.js.map +1 -0
  219. package/lib/mcp/tools/profile-tools.d.ts +59 -0
  220. package/lib/mcp/tools/profile-tools.js +213 -0
  221. package/lib/mcp/tools/profile-tools.js.map +1 -0
  222. package/lib/mcp/tools/summary-tools.d.ts +14 -0
  223. package/lib/mcp/tools/summary-tools.js +38 -0
  224. package/lib/mcp/tools/summary-tools.js.map +1 -0
  225. package/lib/mcp/tools/tool-factory.d.ts +63 -0
  226. package/lib/mcp/tools/tool-factory.js +146 -0
  227. package/lib/mcp/tools/tool-factory.js.map +1 -0
  228. package/lib/mcp/tools/user-tools.d.ts +25 -0
  229. package/lib/mcp/tools/user-tools.js +167 -0
  230. package/lib/mcp/tools/user-tools.js.map +1 -0
  231. package/lib/models/date-literal.d.ts +211 -0
  232. package/lib/models/date-literal.js +615 -0
  233. package/lib/models/date-literal.js.map +1 -0
  234. package/lib/models/object-describe-types.d.ts +173 -0
  235. package/lib/models/object-describe-types.js +9 -0
  236. package/lib/models/object-describe-types.js.map +1 -0
  237. package/lib/models/profile-request-types.d.ts +118 -0
  238. package/lib/models/profile-request-types.js +23 -0
  239. package/lib/models/profile-request-types.js.map +1 -0
  240. package/lib/models/profiling-execution-types.d.ts +154 -0
  241. package/lib/models/profiling-execution-types.js +14 -0
  242. package/lib/models/profiling-execution-types.js.map +1 -0
  243. package/lib/models/service-result.d.ts +114 -0
  244. package/lib/models/service-result.js +81 -0
  245. package/lib/models/service-result.js.map +1 -0
  246. package/lib/models/sfdmu-types.d.ts +53 -0
  247. package/lib/models/sfdmu-types.js +23 -0
  248. package/lib/models/sfdmu-types.js.map +1 -0
  249. package/lib/models/status-types.d.ts +38 -0
  250. package/lib/models/status-types.js +12 -0
  251. package/lib/models/status-types.js.map +1 -0
  252. package/lib/models/summary-bulk-types.d.ts +61 -0
  253. package/lib/models/summary-bulk-types.js +23 -0
  254. package/lib/models/summary-bulk-types.js.map +1 -0
  255. package/lib/models/user-details-types.d.ts +163 -0
  256. package/lib/models/user-details-types.js +9 -0
  257. package/lib/models/user-details-types.js.map +1 -0
  258. package/lib/models/year-range.d.ts +78 -0
  259. package/lib/models/year-range.js +153 -0
  260. package/lib/models/year-range.js.map +1 -0
  261. package/lib/operations/CompatibilityCheckOperation.d.ts +62 -0
  262. package/lib/operations/CompatibilityCheckOperation.js +102 -0
  263. package/lib/operations/CompatibilityCheckOperation.js.map +1 -0
  264. package/lib/operations/DefinitionCreateOperation.d.ts +411 -0
  265. package/lib/operations/DefinitionCreateOperation.js +1121 -0
  266. package/lib/operations/DefinitionCreateOperation.js.map +1 -0
  267. package/lib/operations/DefinitionExportOperation.d.ts +155 -0
  268. package/lib/operations/DefinitionExportOperation.js +281 -0
  269. package/lib/operations/DefinitionExportOperation.js.map +1 -0
  270. package/lib/operations/DefinitionImportOperation.d.ts +144 -0
  271. package/lib/operations/DefinitionImportOperation.js +357 -0
  272. package/lib/operations/DefinitionImportOperation.js.map +1 -0
  273. package/lib/operations/DefinitionListOperation.d.ts +66 -0
  274. package/lib/operations/DefinitionListOperation.js +108 -0
  275. package/lib/operations/DefinitionListOperation.js.map +1 -0
  276. package/lib/operations/DefinitionPurgeOperation.d.ts +199 -0
  277. package/lib/operations/DefinitionPurgeOperation.js +465 -0
  278. package/lib/operations/DefinitionPurgeOperation.js.map +1 -0
  279. package/lib/operations/DefinitionUpdateOperation.d.ts +78 -0
  280. package/lib/operations/DefinitionUpdateOperation.js +142 -0
  281. package/lib/operations/DefinitionUpdateOperation.js.map +1 -0
  282. package/lib/operations/OrgDetailsOperation.d.ts +253 -0
  283. package/lib/operations/OrgDetailsOperation.js +456 -0
  284. package/lib/operations/OrgDetailsOperation.js.map +1 -0
  285. package/lib/operations/OrgResetOperation.d.ts +114 -0
  286. package/lib/operations/OrgResetOperation.js +209 -0
  287. package/lib/operations/OrgResetOperation.js.map +1 -0
  288. package/lib/operations/ProfileOperation.d.ts +187 -0
  289. package/lib/operations/ProfileOperation.js +373 -0
  290. package/lib/operations/ProfileOperation.js.map +1 -0
  291. package/lib/operations/ProfileRequestCancelOperation.d.ts +59 -0
  292. package/lib/operations/ProfileRequestCancelOperation.js +137 -0
  293. package/lib/operations/ProfileRequestCancelOperation.js.map +1 -0
  294. package/lib/operations/ProfileRequestDeleteOperation.d.ts +64 -0
  295. package/lib/operations/ProfileRequestDeleteOperation.js +134 -0
  296. package/lib/operations/ProfileRequestDeleteOperation.js.map +1 -0
  297. package/lib/operations/ProfileRequestListOperation.d.ts +39 -0
  298. package/lib/operations/ProfileRequestListOperation.js +61 -0
  299. package/lib/operations/ProfileRequestListOperation.js.map +1 -0
  300. package/lib/operations/SummaryPurgeOperation.d.ts +134 -0
  301. package/lib/operations/SummaryPurgeOperation.js +257 -0
  302. package/lib/operations/SummaryPurgeOperation.js.map +1 -0
  303. package/lib/operations/SummaryReprofileOperation.d.ts +88 -0
  304. package/lib/operations/SummaryReprofileOperation.js +174 -0
  305. package/lib/operations/SummaryReprofileOperation.js.map +1 -0
  306. package/lib/operations/SummaryStopOperation.d.ts +87 -0
  307. package/lib/operations/SummaryStopOperation.js +175 -0
  308. package/lib/operations/SummaryStopOperation.js.map +1 -0
  309. package/lib/services/BulkExecutionService.d.ts +120 -0
  310. package/lib/services/BulkExecutionService.js +535 -0
  311. package/lib/services/BulkExecutionService.js.map +1 -0
  312. package/lib/services/CompatibilityService.d.ts +81 -0
  313. package/lib/services/CompatibilityService.js +118 -0
  314. package/lib/services/CompatibilityService.js.map +1 -0
  315. package/lib/services/ConfigureMode.d.ts +85 -0
  316. package/lib/services/ConfigureMode.js +390 -0
  317. package/lib/services/ConfigureMode.js.map +1 -0
  318. package/lib/services/ContactPointService.d.ts +111 -0
  319. package/lib/services/ContactPointService.js +286 -0
  320. package/lib/services/ContactPointService.js.map +1 -0
  321. package/lib/services/DataAvailabilityService.d.ts +81 -0
  322. package/lib/services/DataAvailabilityService.js +128 -0
  323. package/lib/services/DataAvailabilityService.js.map +1 -0
  324. package/lib/services/DefinitionFieldGenerationService.d.ts +309 -0
  325. package/lib/services/DefinitionFieldGenerationService.js +795 -0
  326. package/lib/services/DefinitionFieldGenerationService.js.map +1 -0
  327. package/lib/services/DefinitionQueryBuilder.d.ts +59 -0
  328. package/lib/services/DefinitionQueryBuilder.js +234 -0
  329. package/lib/services/DefinitionQueryBuilder.js.map +1 -0
  330. package/lib/services/ObjectDescribeService.d.ts +436 -0
  331. package/lib/services/ObjectDescribeService.js +869 -0
  332. package/lib/services/ObjectDescribeService.js.map +1 -0
  333. package/lib/services/ObjectFilteringService.d.ts +400 -0
  334. package/lib/services/ObjectFilteringService.js +878 -0
  335. package/lib/services/ObjectFilteringService.js.map +1 -0
  336. package/lib/services/ObjectListCommandService.d.ts +429 -0
  337. package/lib/services/ObjectListCommandService.js +873 -0
  338. package/lib/services/ObjectListCommandService.js.map +1 -0
  339. package/lib/services/ObjectListService.d.ts +201 -0
  340. package/lib/services/ObjectListService.js +345 -0
  341. package/lib/services/ObjectListService.js.map +1 -0
  342. package/lib/services/OrgInfoService.d.ts +485 -0
  343. package/lib/services/OrgInfoService.js +1122 -0
  344. package/lib/services/OrgInfoService.js.map +1 -0
  345. package/lib/services/PollingService.d.ts +105 -0
  346. package/lib/services/PollingService.js +117 -0
  347. package/lib/services/PollingService.js.map +1 -0
  348. package/lib/services/ProfileRequestService.d.ts +186 -0
  349. package/lib/services/ProfileRequestService.js +555 -0
  350. package/lib/services/ProfileRequestService.js.map +1 -0
  351. package/lib/services/ProfilingDefinitionService.d.ts +535 -0
  352. package/lib/services/ProfilingDefinitionService.js +981 -0
  353. package/lib/services/ProfilingDefinitionService.js.map +1 -0
  354. package/lib/services/ProfilingExecutionService.d.ts +122 -0
  355. package/lib/services/ProfilingExecutionService.js +320 -0
  356. package/lib/services/ProfilingExecutionService.js.map +1 -0
  357. package/lib/services/ProfilingSummaryService.d.ts +292 -0
  358. package/lib/services/ProfilingSummaryService.js +685 -0
  359. package/lib/services/ProfilingSummaryService.js.map +1 -0
  360. package/lib/services/RecordTypeService.d.ts +129 -0
  361. package/lib/services/RecordTypeService.js +284 -0
  362. package/lib/services/RecordTypeService.js.map +1 -0
  363. package/lib/services/SFDMUService.d.ts +133 -0
  364. package/lib/services/SFDMUService.js +295 -0
  365. package/lib/services/SFDMUService.js.map +1 -0
  366. package/lib/services/TabDetectionService.d.ts +105 -0
  367. package/lib/services/TabDetectionService.js +206 -0
  368. package/lib/services/TabDetectionService.js.map +1 -0
  369. package/lib/services/UnconfigureMode.d.ts +74 -0
  370. package/lib/services/UnconfigureMode.js +378 -0
  371. package/lib/services/UnconfigureMode.js.map +1 -0
  372. package/lib/services/UserConfigurationService.d.ts +155 -0
  373. package/lib/services/UserConfigurationService.js +573 -0
  374. package/lib/services/UserConfigurationService.js.map +1 -0
  375. package/lib/services/UserConfigurationTypes.d.ts +181 -0
  376. package/lib/services/UserConfigurationTypes.js +14 -0
  377. package/lib/services/UserConfigurationTypes.js.map +1 -0
  378. package/lib/services/UserReadinessService.d.ts +330 -0
  379. package/lib/services/UserReadinessService.js +831 -0
  380. package/lib/services/UserReadinessService.js.map +1 -0
  381. package/lib/services/constants.d.ts +53 -0
  382. package/lib/services/constants.js +71 -0
  383. package/lib/services/constants.js.map +1 -0
  384. package/lib/services/namespace-constants.d.ts +1 -0
  385. package/lib/services/namespace-constants.js +11 -0
  386. package/lib/services/namespace-constants.js.map +1 -0
  387. package/lib/services/validation.d.ts +47 -0
  388. package/lib/services/validation.js +119 -0
  389. package/lib/services/validation.js.map +1 -0
  390. package/lib/utils/batch-processor.d.ts +13 -0
  391. package/lib/utils/batch-processor.js +39 -0
  392. package/lib/utils/batch-processor.js.map +1 -0
  393. package/lib/utils/formatting/availability-grid.d.ts +81 -0
  394. package/lib/utils/formatting/availability-grid.js +94 -0
  395. package/lib/utils/formatting/availability-grid.js.map +1 -0
  396. package/lib/utils/formatting/business-process-grid.d.ts +51 -0
  397. package/lib/utils/formatting/business-process-grid.js +58 -0
  398. package/lib/utils/formatting/business-process-grid.js.map +1 -0
  399. package/lib/utils/formatting/command-display.d.ts +154 -0
  400. package/lib/utils/formatting/command-display.js +154 -0
  401. package/lib/utils/formatting/command-display.js.map +1 -0
  402. package/lib/utils/formatting/definition-create-display.d.ts +118 -0
  403. package/lib/utils/formatting/definition-create-display.js +231 -0
  404. package/lib/utils/formatting/definition-create-display.js.map +1 -0
  405. package/lib/utils/formatting/empty-states.d.ts +35 -0
  406. package/lib/utils/formatting/empty-states.js +70 -0
  407. package/lib/utils/formatting/empty-states.js.map +1 -0
  408. package/lib/utils/formatting/errors.d.ts +33 -0
  409. package/lib/utils/formatting/errors.js +72 -0
  410. package/lib/utils/formatting/errors.js.map +1 -0
  411. package/lib/utils/formatting/field-types.d.ts +32 -0
  412. package/lib/utils/formatting/field-types.js +88 -0
  413. package/lib/utils/formatting/field-types.js.map +1 -0
  414. package/lib/utils/formatting/index.d.ts +29 -0
  415. package/lib/utils/formatting/index.js +28 -0
  416. package/lib/utils/formatting/index.js.map +1 -0
  417. package/lib/utils/formatting/indicators.d.ts +113 -0
  418. package/lib/utils/formatting/indicators.js +161 -0
  419. package/lib/utils/formatting/indicators.js.map +1 -0
  420. package/lib/utils/formatting/loading-messages.d.ts +37 -0
  421. package/lib/utils/formatting/loading-messages.js +50 -0
  422. package/lib/utils/formatting/loading-messages.js.map +1 -0
  423. package/lib/utils/formatting/namespace-display.d.ts +31 -0
  424. package/lib/utils/formatting/namespace-display.js +64 -0
  425. package/lib/utils/formatting/namespace-display.js.map +1 -0
  426. package/lib/utils/formatting/numbers.d.ts +73 -0
  427. package/lib/utils/formatting/numbers.js +187 -0
  428. package/lib/utils/formatting/numbers.js.map +1 -0
  429. package/lib/utils/formatting/object-describe-display.d.ts +114 -0
  430. package/lib/utils/formatting/object-describe-display.js +440 -0
  431. package/lib/utils/formatting/object-describe-display.js.map +1 -0
  432. package/lib/utils/formatting/object-list-display.d.ts +213 -0
  433. package/lib/utils/formatting/object-list-display.js +672 -0
  434. package/lib/utils/formatting/object-list-display.js.map +1 -0
  435. package/lib/utils/formatting/org-identity.d.ts +15 -0
  436. package/lib/utils/formatting/org-identity.js +28 -0
  437. package/lib/utils/formatting/org-identity.js.map +1 -0
  438. package/lib/utils/formatting/record-age-grid.d.ts +41 -0
  439. package/lib/utils/formatting/record-age-grid.js +56 -0
  440. package/lib/utils/formatting/record-age-grid.js.map +1 -0
  441. package/lib/utils/formatting/sections.d.ts +108 -0
  442. package/lib/utils/formatting/sections.js +150 -0
  443. package/lib/utils/formatting/sections.js.map +1 -0
  444. package/lib/utils/formatting/tables.d.ts +90 -0
  445. package/lib/utils/formatting/tables.js +113 -0
  446. package/lib/utils/formatting/tables.js.map +1 -0
  447. package/lib/utils/formatting/user-details-display.d.ts +101 -0
  448. package/lib/utils/formatting/user-details-display.js +425 -0
  449. package/lib/utils/formatting/user-details-display.js.map +1 -0
  450. package/lib/utils/pagination/index.d.ts +11 -0
  451. package/lib/utils/pagination/index.js +18 -0
  452. package/lib/utils/pagination/index.js.map +1 -0
  453. package/lib/utils/pagination/keypress-reader.d.ts +20 -0
  454. package/lib/utils/pagination/keypress-reader.js +63 -0
  455. package/lib/utils/pagination/keypress-reader.js.map +1 -0
  456. package/lib/utils/pagination/paginate-output.d.ts +48 -0
  457. package/lib/utils/pagination/paginate-output.js +136 -0
  458. package/lib/utils/pagination/paginate-output.js.map +1 -0
  459. package/messages/compatibility.check.md +71 -0
  460. package/messages/cuneiform.access.md +138 -0
  461. package/messages/definition.create.md +511 -0
  462. package/messages/definition.export.md +84 -0
  463. package/messages/definition.get.md +147 -0
  464. package/messages/definition.import.md +65 -0
  465. package/messages/definition.list.md +264 -0
  466. package/messages/definition.purge.md +318 -0
  467. package/messages/definition.update.md +118 -0
  468. package/messages/mcp.serve.md +66 -0
  469. package/messages/object.describe.md +201 -0
  470. package/messages/object.list.md +443 -0
  471. package/messages/org.details.md +386 -0
  472. package/messages/org.reset.md +71 -0
  473. package/messages/profile.md +231 -0
  474. package/messages/profile.request.cancel.md +143 -0
  475. package/messages/profile.request.delete.md +139 -0
  476. package/messages/profile.request.list.md +89 -0
  477. package/messages/summary.purge.md +218 -0
  478. package/messages/summary.reprofile.md +150 -0
  479. package/messages/summary.stop.md +157 -0
  480. package/messages/user.details.md +501 -0
  481. package/oclif.lock +2887 -2149
  482. package/oclif.manifest.json +2813 -31
  483. package/package.json +94 -19
  484. package/lib/commands/cuneiform/about.d.ts +0 -13
  485. package/lib/commands/cuneiform/about.js +0 -26
  486. package/lib/commands/cuneiform/about.js.map +0 -1
  487. package/lib/commands/hello/world.d.ts +0 -14
  488. package/lib/commands/hello/world.js +0 -27
  489. package/lib/commands/hello/world.js.map +0 -1
  490. package/lib/index.d.ts +0 -2
  491. package/lib/index.js +0 -2
  492. package/lib/index.js.map +0 -1
  493. package/messages/cuneiform.about.md +0 -19
  494. package/messages/hello.world.md +0 -29
@@ -0,0 +1,878 @@
1
+ /*
2
+ * Copyright (c) 2026, PeerNova, Inc. All Rights Reserved.
3
+ * PROPRIETARY AND CONFIDENTIAL. Unauthorized copying, modification,
4
+ * or distribution is strictly prohibited. Use is governed by the
5
+ * Master Subscription Agreement (MSA) between PeerNova, Inc. and the
6
+ * licensee. See LICENSE file in the repo root.
7
+ */
8
+ import { CuneiformQueryBuilder } from '../adapters/soql/cuneiform-query-builder.js';
9
+ import { createSuccessResult, createFailureResult } from '../models/service-result.js';
10
+ import { ServiceErrorCodes } from '../adapters/errors.js';
11
+ import { processInBatches } from '../utils/batch-processor.js';
12
+ import { validateNamespace, validateNonEmptyArray } from './validation.js';
13
+ import { MAX_OBJECT_NAMES } from './constants.js';
14
+ /** Default number of objects to process concurrently in checkDataExistsInRange. */
15
+ const DEFAULT_CONCURRENCY_LIMIT = 5;
16
+ /** Valid type filter values */
17
+ const VALID_TYPES = new Set(['standard', 'custom', 'all']);
18
+ /** Valid name filter operators */
19
+ const VALID_OPERATORS = new Set(['startsWith', 'contains', 'equals', 'wildcard']);
20
+ /** Valid classification values */
21
+ const VALID_CLASSIFICATIONS = new Set(['customer', 'internal', 'all']);
22
+ /** Namespace format pattern: starts with letter, alphanumeric only */
23
+ const NAMESPACE_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;
24
+ /**
25
+ * Object API name suffixes that indicate non-data objects which are never valid
26
+ * profiling targets: `__mdt` (Custom Metadata Types — configuration, not data),
27
+ * `__History` (change-tracking auxiliary), `__Share` (sharing-rule auxiliary),
28
+ * `__Feed` (Chatter feed auxiliary), `__ChangeEvent` (Change Data Capture event),
29
+ * `__e` (Platform Events — no persistent records).
30
+ *
31
+ * Big Objects (`__b`) and External Objects (`__x`) are intentionally excluded
32
+ * from this list — they hold queryable records and remain valid profiling
33
+ * targets, gated by the layoutable/keyPrefix predicate alone.
34
+ *
35
+ * The layoutable + keyPrefix predicate alone is insufficient: in some orgs
36
+ * Custom Metadata Types report `IsLayoutable=true` and a non-null KeyPrefix
37
+ * (e.g., m00) and end up in the `customer` EntityDefinition set — see CLI-3085.
38
+ * The ISV REST `filter-objects` endpoint does not honor `excludeSystemObjects`
39
+ * for `__mdt` either, so the CLI applies this name-based safety filter on both
40
+ * the local SOQL path and the REST response.
41
+ */
42
+ const NON_DATA_SUFFIX_PATTERN = /__(mdt|History|Share|Feed|ChangeEvent|e)$/;
43
+ /**
44
+ * Domain service for filtering and classifying Salesforce objects.
45
+ *
46
+ * Provides methods to filter objects by type, namespace, classification,
47
+ * record counts, and record types. Uses describeGlobal for metadata,
48
+ * EntityDefinition SOQL for customer/internal classification, and
49
+ * lazy-loads record type information via SOQL.
50
+ *
51
+ * @design
52
+ * **File Size**: This file is ~630 lines, larger than the ideal 200-400 line target.
53
+ * This is intentional: all filter logic, validation, and transformation code is
54
+ * cohesive and related. Splitting into multiple files would force readers to jump
55
+ * between files to understand the filter chain, hurting confidence and clarity.
56
+ * Per Human-Centered Code Principles, "Confidence > Maintainability" — a cohesive
57
+ * file beats scattered fragments.
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const service = new ObjectFilteringService({
62
+ * restApiAdapter,
63
+ * soqlAdapter,
64
+ * logger: console,
65
+ * });
66
+ *
67
+ * // Filter custom objects with records
68
+ * const result = await service.filter({
69
+ * type: 'custom',
70
+ * withRecords: true,
71
+ * });
72
+ *
73
+ * if (result.success) {
74
+ * for (const obj of result.data) {
75
+ * console.log(`${obj.name}: ${obj.recordCount} records`);
76
+ * }
77
+ * }
78
+ * ```
79
+ */
80
+ export class ObjectFilteringService {
81
+ restApiAdapter;
82
+ soqlAdapter;
83
+ concurrencyLimit;
84
+ logger;
85
+ restClient;
86
+ /** Lazily loaded set of object names that have active record types */
87
+ recordTypeCache = null;
88
+ /** Cache of object names that have an OwnerId field (per-session) */
89
+ ownerFieldCache = new Map();
90
+ /** Lazily loaded set of customer-facing object names from EntityDefinition (per-session) */
91
+ customerObjectCache = null;
92
+ /**
93
+ * Creates a new ObjectFilteringService.
94
+ *
95
+ * @param config - Service configuration with required adapters
96
+ */
97
+ constructor(config) {
98
+ this.restApiAdapter = config.restApiAdapter;
99
+ this.soqlAdapter = config.soqlAdapter;
100
+ this.concurrencyLimit = config.concurrencyLimit ?? DEFAULT_CONCURRENCY_LIMIT;
101
+ this.logger = config.logger;
102
+ this.restClient = config.restClient;
103
+ }
104
+ /**
105
+ * Validates filter options and returns a failure result if invalid.
106
+ *
107
+ * @param options - The filter options to validate
108
+ * @returns A failure ServiceResult if validation fails, undefined otherwise
109
+ */
110
+ static validateFilterOptions(options) {
111
+ // Validate type
112
+ if (options.type !== undefined && !VALID_TYPES.has(options.type)) {
113
+ return createFailureResult([], ServiceErrorCodes.INVALID_TYPE, `Invalid type parameter: "${options.type}". Must be 'standard', 'custom', or 'all'.`);
114
+ }
115
+ // Validate namespace (only if it's a non-null string)
116
+ if (options.namespace !== undefined && options.namespace !== null) {
117
+ if (!NAMESPACE_PATTERN.test(options.namespace)) {
118
+ return createFailureResult([], ServiceErrorCodes.INVALID_NAMESPACE, `Invalid namespace format: "${options.namespace}". Must start with a letter and contain only letters and numbers.`);
119
+ }
120
+ }
121
+ // Validate name filter
122
+ if (options.nameFilter) {
123
+ if (!options.nameFilter.value || options.nameFilter.value.trim().length === 0) {
124
+ return createFailureResult([], ServiceErrorCodes.INVALID_NAME_FILTER, 'Name filter value is required and cannot be empty.');
125
+ }
126
+ if (!VALID_OPERATORS.has(options.nameFilter.operator)) {
127
+ return createFailureResult([], ServiceErrorCodes.INVALID_NAME_FILTER, `Invalid name filter operator: "${options.nameFilter.operator}". Must be 'startsWith', 'contains', 'equals', or 'wildcard'.`);
128
+ }
129
+ // For wildcard operator, validate that pattern contains at least one *
130
+ if (options.nameFilter.operator === 'wildcard' && !options.nameFilter.value.includes('*')) {
131
+ return createFailureResult([], ServiceErrorCodes.INVALID_NAME_FILTER, `Wildcard pattern must contain at least one '*' character. Got: "${options.nameFilter.value}".`);
132
+ }
133
+ }
134
+ // Validate classification
135
+ if (options.classification !== undefined && !VALID_CLASSIFICATIONS.has(options.classification)) {
136
+ return createFailureResult([], ServiceErrorCodes.INVALID_CLASSIFICATION, `Invalid classification: "${options.classification}". Must be 'customer', 'internal', or 'all'.`);
137
+ }
138
+ return undefined;
139
+ }
140
+ /**
141
+ * Determines whether an object is custom.
142
+ * Custom object detection: name ends with __c OR custom === true.
143
+ *
144
+ * @param obj - The global describe object to check
145
+ * @returns True if the object is custom
146
+ */
147
+ static isCustomObject(obj) {
148
+ return obj.custom || obj.name.endsWith('__c');
149
+ }
150
+ /**
151
+ * Extracts namespace from an object API name.
152
+ * Namespaced objects follow the pattern: namespace__ObjectName__c
153
+ *
154
+ * @param name - The object API name
155
+ * @returns The namespace prefix, or undefined if unmanaged
156
+ */
157
+ static extractNamespace(name) {
158
+ // Namespace pattern: at least two double-underscore segments
159
+ // e.g., ns__Object__c -> ns, ns__Object -> ns
160
+ // Standard objects and non-namespaced custom objects have at most one __
161
+ const parts = name.split('__');
162
+ if (parts.length >= 3) {
163
+ // ns__Object__c or ns__Object__suffix
164
+ return parts[0];
165
+ }
166
+ return undefined;
167
+ }
168
+ /**
169
+ * Converts a global describe result to SObjectInfo.
170
+ *
171
+ * @param obj - The global describe object
172
+ * @returns SObjectInfo representation
173
+ */
174
+ static toSObjectInfo(obj) {
175
+ const info = {
176
+ name: obj.name,
177
+ label: obj.label,
178
+ isCustom: ObjectFilteringService.isCustomObject(obj),
179
+ };
180
+ const namespace = ObjectFilteringService.extractNamespace(obj.name);
181
+ if (namespace) {
182
+ info.namespace = namespace;
183
+ }
184
+ return info;
185
+ }
186
+ /**
187
+ * Applies type filter to objects.
188
+ */
189
+ static applyTypeFilter(objects, type) {
190
+ if (type === 'custom') {
191
+ return objects.filter((obj) => ObjectFilteringService.isCustomObject(obj));
192
+ }
193
+ // standard
194
+ return objects.filter((obj) => !ObjectFilteringService.isCustomObject(obj));
195
+ }
196
+ /**
197
+ * Applies namespace filter to objects.
198
+ */
199
+ static applyNamespaceFilter(objects, namespace) {
200
+ if (namespace === null) {
201
+ // null means unmanaged -- no namespace
202
+ return objects.filter((obj) => !ObjectFilteringService.extractNamespace(obj.name));
203
+ }
204
+ // Match specific namespace (case-insensitive)
205
+ // Salesforce namespaces are case-insensitive in org references and API calls
206
+ const lowerNamespace = namespace.toLowerCase();
207
+ return objects.filter((obj) => {
208
+ const ns = ObjectFilteringService.extractNamespace(obj.name);
209
+ return ns !== undefined && ns.toLowerCase() === lowerNamespace;
210
+ });
211
+ }
212
+ /**
213
+ * Converts a wildcard pattern (with *) to a regular expression.
214
+ * The * character matches any sequence of characters.
215
+ *
216
+ * @param pattern - The wildcard pattern (e.g., "Account*", "*__c", "*Contact*")
217
+ * @returns A RegExp that matches the pattern case-insensitively
218
+ */
219
+ static wildcardToRegex(pattern) {
220
+ // Escape special regex characters except *
221
+ const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
222
+ // Convert * to .* (match any characters)
223
+ const regexPattern = escaped.replace(/\*/g, '.*');
224
+ // Anchor the pattern and make it case-insensitive
225
+ return new RegExp(`^${regexPattern}$`, 'i');
226
+ }
227
+ /**
228
+ * Applies name filter to objects (case-insensitive).
229
+ */
230
+ static applyNameFilter(objects, nameFilter) {
231
+ const lowerValue = nameFilter.value.toLowerCase();
232
+ // Pre-compile regex for wildcard operator
233
+ const wildcardRegex = nameFilter.operator === 'wildcard' ? ObjectFilteringService.wildcardToRegex(nameFilter.value) : null;
234
+ return objects.filter((obj) => {
235
+ const lowerName = obj.name.toLowerCase();
236
+ switch (nameFilter.operator) {
237
+ case 'startsWith':
238
+ return lowerName.startsWith(lowerValue);
239
+ case 'contains':
240
+ return lowerName.includes(lowerValue);
241
+ case 'equals':
242
+ return lowerName === lowerValue;
243
+ case 'wildcard':
244
+ return wildcardRegex.test(obj.name);
245
+ default:
246
+ return false;
247
+ }
248
+ });
249
+ }
250
+ /**
251
+ * Applies system object exclusion. Excludes objects that are not valid profiling
252
+ * targets: layoutable === false OR keyPrefix === null (auxiliary/system objects),
253
+ * OR name matches NON_DATA_SUFFIX_PATTERN (CLI-3085: Salesforce reports
254
+ * IsLayoutable=true and a non-null KeyPrefix for Custom Metadata Types in some
255
+ * orgs, so the layoutable/keyPrefix predicate alone is insufficient).
256
+ */
257
+ static applySystemObjectExclusion(objects) {
258
+ return objects.filter((obj) => {
259
+ const layoutable = obj.layoutable ?? true;
260
+ if (!layoutable || obj.keyPrefix === null)
261
+ return false;
262
+ if (NON_DATA_SUFFIX_PATTERN.test(obj.name))
263
+ return false;
264
+ return true;
265
+ });
266
+ }
267
+ /**
268
+ * Predicate filter: keep only objects with `recordCount > 0`.
269
+ *
270
+ * Operates on already-populated counts produced by {@link populateRecordCounts};
271
+ * does not perform any API calls. Objects whose count was not populated (undefined
272
+ * recordCount, e.g. when the count query failed) are excluded — only positively
273
+ * confirmed non-zero counts pass.
274
+ */
275
+ static applyWithRecordsFilter(objects) {
276
+ return objects.filter((obj) => (obj.recordCount ?? 0) > 0);
277
+ }
278
+ /**
279
+ * Predicate filter: keep only objects with `recordCount === 0`.
280
+ *
281
+ * Operates on already-populated counts produced by {@link populateRecordCounts};
282
+ * does not perform any API calls. Objects whose count was not populated (undefined
283
+ * recordCount) are excluded — only positively confirmed zero counts pass.
284
+ */
285
+ static applyWithoutRecordsFilter(objects) {
286
+ return objects.filter((obj) => obj.recordCount === 0);
287
+ }
288
+ /**
289
+ * Applies withRecords or withoutRecords locally after REST delegation.
290
+ * Called when the Apex endpoint has returned a candidate list that still needs
291
+ * record-count filtering — the server intentionally does not do this step.
292
+ */
293
+ static applyPostRestRecordCountFilter(results, options) {
294
+ if (options.withRecords) {
295
+ return ObjectFilteringService.applyWithRecordsFilter(results);
296
+ }
297
+ if (options.withoutRecords) {
298
+ return ObjectFilteringService.applyWithoutRecordsFilter(results);
299
+ }
300
+ return results;
301
+ }
302
+ /**
303
+ * Excludes Custom Settings (list and hierarchy) from describe results.
304
+ * Custom Settings are configuration objects, not business data objects.
305
+ * Protected Custom Settings (visibility=Protected) must never be visible to subscribers.
306
+ */
307
+ static applyCustomSettingExclusion(objects) {
308
+ return objects.filter((obj) => !obj.customSetting);
309
+ }
310
+ /**
311
+ * Filters Salesforce objects based on combined filter criteria.
312
+ *
313
+ * Applies filters in order from cheapest to most expensive:
314
+ * type -> namespace -> nameFilter -> classification -> excludeSystemObjects -> customSettings -> withRecords -> hasRecordTypes
315
+ *
316
+ * @param options - Filter criteria to apply
317
+ * @returns ServiceResult containing filtered SObjectInfo array
318
+ */
319
+ async filter(options) {
320
+ const startTime = Date.now();
321
+ try {
322
+ // Validate inputs
323
+ const validationError = ObjectFilteringService.validateFilterOptions(options);
324
+ if (validationError) {
325
+ return validationError;
326
+ }
327
+ // REST API path: delegate metadata filtering to the server when restClient is available.
328
+ // withRecords/withoutRecords are intentionally NOT delegated — the server-side path uses
329
+ // per-object SOQL COUNT() queries that exhaust the governor budget on large orgs, causing
330
+ // objects without records to slip through (CLI-3083). The CLI applies them locally via
331
+ // GET /limits/recordCount (single call, no SOQL cost). Falls back to the local path on
332
+ // failure (e.g., endpoint not deployed).
333
+ const restFallbackResult = await this.tryRestDelegation(options, startTime);
334
+ if (restFallbackResult) {
335
+ const restResults = ObjectFilteringService.applyPostRestRecordCountFilter(restFallbackResult.data, options);
336
+ return createSuccessResult(restResults, {
337
+ message: `Found ${restResults.length} objects matching filter criteria`,
338
+ metadata: { duration: Date.now() - startTime, strategyUsed: 'rest-api' },
339
+ });
340
+ }
341
+ // Fetch global describe (local path)
342
+ const globalResult = await this.restApiAdapter.describeGlobal();
343
+ if (!globalResult.success) {
344
+ return createFailureResult([], ServiceErrorCodes.FILTER_FAILED, globalResult.message ?? 'Global describe failed', {
345
+ metadata: { duration: Date.now() - startTime },
346
+ });
347
+ }
348
+ let sobjects = globalResult.data.sobjects;
349
+ // ─────────────────────────────────────────────────────────────────────────
350
+ // Filter Application Order (cheapest → most expensive)
351
+ // ─────────────────────────────────────────────────────────────────────────
352
+ // Filters are deliberately ordered to minimize work:
353
+ // 0. non-profileable — drop non-queryable objects (mirrors server-side
354
+ // applyNonProfileableFilters in pnova/ObjectFilterRestService.cls).
355
+ // Non-queryable objects (FeedTrackedChange, etc.) cannot be profiled,
356
+ // so they must never appear in any classification bucket. Without
357
+ // this gate, the local fallback returned a superset of the REST path
358
+ // for `--classification customer|internal` (CLI-3310).
359
+ // 1. type — in-memory flag check (instant)
360
+ // 2. namespace — string parsing (instant)
361
+ // 3. nameFilter — string comparison (instant)
362
+ // 4. classification — 1 SOQL query (cached after first call)
363
+ // 5. excludeSystem — in-memory flag check (instant)
364
+ // 6. customSettings — in-memory flag check (instant, uses describe already fetched)
365
+ // 7. populate counts — 1 bulk REST call against the bounded result set.
366
+ // The Records column is part of the documented output contract — counts
367
+ // must be queried unconditionally so that "0" never doubles as a placeholder
368
+ // for "we didn't ask". `withRecords` / `withoutRecords` are predicates,
369
+ // not population gates (CLI-3077).
370
+ // 8. withRecords — predicate against populated counts (no API call)
371
+ // 9. withoutRecords — predicate against populated counts (no API call)
372
+ // 10. hasRecordTypes — 1 SOQL query (cached after first call)
373
+ // 11. withOwner — N describe calls (1 per uncached object)
374
+ // ─────────────────────────────────────────────────────────────────────────
375
+ // 0. Non-profileable exclusion — match server's applyNonProfileableFilters.
376
+ // Use !== false so that objects where queryable is absent in the API
377
+ // response are kept rather than silently dropped.
378
+ sobjects = sobjects.filter((obj) => obj.queryable !== false);
379
+ // 1. Type filter (instant)
380
+ if (options.type && options.type !== 'all') {
381
+ sobjects = ObjectFilteringService.applyTypeFilter(sobjects, options.type);
382
+ }
383
+ // 2. Namespace filter (instant)
384
+ if (options.namespace !== undefined) {
385
+ sobjects = ObjectFilteringService.applyNamespaceFilter(sobjects, options.namespace);
386
+ }
387
+ // 3. Name filter (instant)
388
+ if (options.nameFilter) {
389
+ sobjects = ObjectFilteringService.applyNameFilter(sobjects, options.nameFilter);
390
+ }
391
+ // 4. Classification filter (1 SOQL query, cached after first call)
392
+ if (options.classification && options.classification !== 'all') {
393
+ sobjects = await this.applyClassificationFilter(sobjects, options.classification);
394
+ }
395
+ // 5. System object exclusion (instant)
396
+ if (options.excludeSystemObjects) {
397
+ sobjects = ObjectFilteringService.applySystemObjectExclusion(sobjects);
398
+ }
399
+ // 6. Custom Setting exclusion (instant — flag already present in global describe)
400
+ sobjects = ObjectFilteringService.applyCustomSettingExclusion(sobjects);
401
+ // Convert to SObjectInfo before expensive operations
402
+ let results = sobjects.map((obj) => ObjectFilteringService.toSObjectInfo(obj));
403
+ // Populate isCustomer classification if EntityDefinition cache is available
404
+ if (this.customerObjectCache !== null) {
405
+ results = results.map((obj) => ({ ...obj, isCustomer: this.customerObjectCache.has(obj.name) }));
406
+ }
407
+ // 6. Populate recordCount unconditionally (single bulk REST call). When the
408
+ // caller asked to filter by record count, the populate step must succeed —
409
+ // we can't honestly say "objects with records" if we don't know counts.
410
+ const countsRequired = options.withRecords === true || options.withoutRecords === true;
411
+ results = await this.populateRecordCounts(results, countsRequired);
412
+ // 7. withRecords filter (predicate against populated counts)
413
+ if (options.withRecords) {
414
+ results = ObjectFilteringService.applyWithRecordsFilter(results);
415
+ }
416
+ // 8. withoutRecords filter (predicate against populated counts)
417
+ if (options.withoutRecords) {
418
+ results = ObjectFilteringService.applyWithoutRecordsFilter(results);
419
+ }
420
+ // 9. hasRecordTypes filter (expensive — 1 SOQL query, cached after first call)
421
+ if (options.hasRecordTypes) {
422
+ results = await this.applyHasRecordTypesFilter(results);
423
+ }
424
+ // 10. withOwner filter (expensive — N API calls, 1 describe per uncached object)
425
+ if (options.withOwner) {
426
+ results = await this.applyWithOwnerFilter(results);
427
+ }
428
+ const duration = Date.now() - startTime;
429
+ this.logger?.log(`Filter returned ${results.length} objects in ${duration}ms`);
430
+ return createSuccessResult(results, {
431
+ message: `Found ${results.length} objects matching filter criteria`,
432
+ metadata: { duration },
433
+ });
434
+ }
435
+ catch (error) {
436
+ const errorMessage = error instanceof Error ? error.message : String(error);
437
+ this.logger?.log(`Filter failed: ${errorMessage}`);
438
+ return createFailureResult([], ServiceErrorCodes.FILTER_FAILED, errorMessage, {
439
+ metadata: { duration: Date.now() - startTime },
440
+ });
441
+ }
442
+ }
443
+ /**
444
+ * Filters objects by type (standard or custom).
445
+ *
446
+ * @param type - The object type to filter by
447
+ * @returns ServiceResult containing filtered SObjectInfo array
448
+ */
449
+ async filterByType(type) {
450
+ if (!VALID_TYPES.has(type)) {
451
+ return createFailureResult([], ServiceErrorCodes.INVALID_TYPE, `Invalid type parameter: "${type}". Must be 'standard', 'custom', or 'all'.`);
452
+ }
453
+ return this.filter({ type });
454
+ }
455
+ /**
456
+ * Filters objects by namespace.
457
+ *
458
+ * @param namespace - The namespace to filter by, or null for unmanaged objects
459
+ * @returns ServiceResult containing filtered SObjectInfo array
460
+ */
461
+ async filterByNamespace(namespace) {
462
+ if (namespace !== null) {
463
+ const error = validateNamespace(namespace);
464
+ if (error) {
465
+ return createFailureResult([], ServiceErrorCodes.INVALID_NAMESPACE, error);
466
+ }
467
+ }
468
+ return this.filter({ namespace });
469
+ }
470
+ /**
471
+ * Filters objects to only those with records (record count > 0).
472
+ *
473
+ * @returns ServiceResult containing filtered SObjectInfo array
474
+ */
475
+ async filterWithRecords() {
476
+ return this.filter({ withRecords: true });
477
+ }
478
+ /**
479
+ * Retrieves SObjectInfo for specific object names.
480
+ *
481
+ * Returns success with data for found objects and warnings for missing ones.
482
+ * If none are found, returns success with empty data and warnings.
483
+ *
484
+ * @param objectNames - Array of object API names to look up
485
+ * @returns ServiceResult containing found SObjectInfo array with warnings for missing
486
+ */
487
+ async getObjectsByName(objectNames) {
488
+ const startTime = Date.now();
489
+ // Validate input
490
+ const validationError = validateNonEmptyArray(objectNames, 'objectNames', MAX_OBJECT_NAMES);
491
+ if (validationError) {
492
+ return createFailureResult([], ServiceErrorCodes.INVALID_OBJECT_NAMES, validationError);
493
+ }
494
+ try {
495
+ // Fetch global describe
496
+ const globalResult = await this.restApiAdapter.describeGlobal();
497
+ if (!globalResult.success) {
498
+ return createFailureResult([], ServiceErrorCodes.FILTER_FAILED, globalResult.message ?? 'Global describe failed', {
499
+ metadata: { duration: Date.now() - startTime },
500
+ });
501
+ }
502
+ // Build a lookup map (case-insensitive)
503
+ const objectMap = new Map();
504
+ for (const obj of globalResult.data.sobjects) {
505
+ objectMap.set(obj.name.toLowerCase(), obj);
506
+ }
507
+ const found = [];
508
+ const warnings = [];
509
+ for (const name of objectNames) {
510
+ const obj = objectMap.get(name.toLowerCase());
511
+ if (obj) {
512
+ found.push(ObjectFilteringService.toSObjectInfo(obj));
513
+ }
514
+ else {
515
+ warnings.push(`Object not found: ${name}`);
516
+ }
517
+ }
518
+ const duration = Date.now() - startTime;
519
+ this.logger?.log(`getObjectsByName: found ${found.length}/${objectNames.length} objects in ${duration}ms`);
520
+ return createSuccessResult(found, {
521
+ message: `Found ${found.length} of ${objectNames.length} requested objects`,
522
+ warnings: warnings.length > 0 ? warnings : undefined,
523
+ metadata: { duration },
524
+ });
525
+ }
526
+ catch (error) {
527
+ const errorMessage = error instanceof Error ? error.message : String(error);
528
+ this.logger?.log(`getObjectsByName failed: ${errorMessage}`);
529
+ return createFailureResult([], ServiceErrorCodes.FILTER_FAILED, errorMessage, {
530
+ metadata: { duration: Date.now() - startTime },
531
+ });
532
+ }
533
+ }
534
+ /**
535
+ * Retrieves record counts for the specified objects using the Record Count API.
536
+ *
537
+ * @param objectNames - Array of object API names to get counts for
538
+ * @returns ServiceResult containing a map of object name to record count
539
+ */
540
+ async getRecordCounts(objectNames) {
541
+ return this.restApiAdapter.getRecordCounts(objectNames);
542
+ }
543
+ /**
544
+ * Checks whether data exists for each probe specification using LIMIT 1 SOQL probes.
545
+ *
546
+ * Returns a flat grid of per-probe boolean results. Each probe uses a
547
+ * `SELECT Id FROM {Object} WHERE CreatedDate >= {yearStart} AND CreatedDate < {yearEnd} LIMIT 1`
548
+ * query to determine data presence efficiently. When a probe includes a `recordType`,
549
+ * a `RecordType.DeveloperName = '{value}'` filter is added.
550
+ *
551
+ * Probes are grouped by object and processed one object at a time. All probes for a single
552
+ * object (across years and record types) run concurrently, then the next object's probes fire.
553
+ * This keeps concurrent SOQL queries scoped to a single object's probes.
554
+ *
555
+ * Failures on individual probes are captured per-entry (hasData=false, error set) rather
556
+ * than failing the entire operation — the grid is informational, not blocking.
557
+ *
558
+ * @param probes - Array of probe specifications to execute
559
+ * @returns ServiceResult containing the availability grid
560
+ */
561
+ async checkDataExistsInRange(probes) {
562
+ const startTime = Date.now();
563
+ const grid = [];
564
+ if (probes.length === 0) {
565
+ return createSuccessResult(grid, {
566
+ message: 'No probes to check',
567
+ metadata: { duration: Date.now() - startTime },
568
+ });
569
+ }
570
+ // Group probes by object for per-object concurrent execution
571
+ const grouped = new Map();
572
+ for (const probe of probes) {
573
+ const existing = grouped.get(probe.objectApiName);
574
+ if (existing) {
575
+ existing.push(probe);
576
+ }
577
+ else {
578
+ grouped.set(probe.objectApiName, [probe]);
579
+ }
580
+ }
581
+ // Process objects in batched parallel groups; probes within each object run concurrently
582
+ const groupedEntries = [...grouped.entries()];
583
+ const batchedResults = await processInBatches(groupedEntries, this.concurrencyLimit, async ([objectName, objectProbes]) => {
584
+ const results = await Promise.all(objectProbes.map((spec) => this.probeDataForYear(spec)));
585
+ this.logger?.log(`Data probes for ${objectName}: ${objectProbes.length} probes`);
586
+ return results;
587
+ });
588
+ for (const results of batchedResults) {
589
+ grid.push(...results);
590
+ }
591
+ const duration = Date.now() - startTime;
592
+ const gapsCount = grid.filter((e) => !e.hasData && !e.error).length;
593
+ const errorsCount = grid.filter((e) => e.error !== undefined).length;
594
+ this.logger?.log(`Data availability check: ${grid.length} probes, ${gapsCount} gaps, ${errorsCount} errors in ${duration}ms`);
595
+ return createSuccessResult(grid, {
596
+ message: `Checked ${grid.length} probe combinations`,
597
+ metadata: { duration },
598
+ });
599
+ }
600
+ /**
601
+ * Probes a single object/year/recordType combination with a LIMIT 1 SOQL query.
602
+ * Returns a DataAvailabilityEntry — never throws.
603
+ */
604
+ async probeDataForYear(spec) {
605
+ const { objectApiName, year, recordType } = spec;
606
+ const yearStart = `${year}-01-01T00:00:00Z`;
607
+ const yearEnd = `${year + 1}-01-01T00:00:00Z`;
608
+ const builder = CuneiformQueryBuilder.create().select(['Id']).from(objectApiName);
609
+ if (recordType) {
610
+ builder.where('RecordType.DeveloperName', '=', recordType);
611
+ builder.andWhereDatetime('CreatedDate', '>=', yearStart);
612
+ }
613
+ else {
614
+ builder.whereDatetime('CreatedDate', '>=', yearStart);
615
+ }
616
+ const soql = builder.andWhereDatetime('CreatedDate', '<', yearEnd).limit(1).toSOQL();
617
+ const label = recordType ? `${objectApiName}/${recordType}/${year}` : `${objectApiName}/${year}`;
618
+ try {
619
+ const result = await this.soqlAdapter.query(soql);
620
+ if (!result.success) {
621
+ this.logger?.log(`Data probe failed for ${label}: ${result.message ?? 'unknown error'}`);
622
+ return { objectApiName, year, hasData: false, error: result.message ?? 'Query failed', recordType };
623
+ }
624
+ return { objectApiName, year, hasData: result.data.records.length > 0, recordType };
625
+ }
626
+ catch (error) {
627
+ const errorMessage = error instanceof Error ? error.message : String(error);
628
+ this.logger?.log(`Data probe exception for ${label}: ${errorMessage}`);
629
+ return { objectApiName, year, hasData: false, error: errorMessage, recordType };
630
+ }
631
+ }
632
+ /**
633
+ * Attempts REST delegation for object filtering.
634
+ * Returns the successful result, or null to signal fallback to the local SOQL path.
635
+ */
636
+ async tryRestDelegation(options, startTime) {
637
+ if (!this.restClient) {
638
+ return null;
639
+ }
640
+ const restResult = await this.filterViaRest(options, startTime);
641
+ if (restResult.success) {
642
+ return restResult;
643
+ }
644
+ this.logger?.log(`REST filter-objects failed (${restResult.message ?? 'unknown'}), falling back to local SOQL path`);
645
+ return null;
646
+ }
647
+ /**
648
+ * Lazily loads and caches the set of customer-facing object names from EntityDefinition.
649
+ * Uses a SOQL query against EntityDefinition to classify objects based on Salesforce metadata
650
+ * rather than hardcoded exclusion lists.
651
+ *
652
+ * @returns Set of customer-facing object API names
653
+ */
654
+ /**
655
+ * Delegates object filtering to the ISV REST API (filter-objects endpoint).
656
+ * Server handles the full cost-optimized filter chain.
657
+ */
658
+ async filterViaRest(options, startTime) {
659
+ this.logger?.log('Delegating object filtering to ISV REST API (filter-objects)');
660
+ const restResult = await this.restClient.filterObjects({
661
+ type: options.type,
662
+ namespace: options.namespace === null ? '' : options.namespace,
663
+ excludeSystemObjects: options.excludeSystemObjects,
664
+ namePattern: options.nameFilter?.value,
665
+ nameOperator: options.nameFilter?.operator,
666
+ classification: options.classification,
667
+ hasRecordTypes: options.hasRecordTypes,
668
+ withOwner: options.withOwner,
669
+ });
670
+ if (!restResult.success) {
671
+ return createFailureResult([], ServiceErrorCodes.FILTER_FAILED, restResult.message ?? 'REST filter-objects failed', {
672
+ metadata: { duration: Date.now() - startTime },
673
+ });
674
+ }
675
+ const response = restResult.data;
676
+ if (!response.success) {
677
+ const errorMsg = response.errors?.length > 0 ? response.errors[0] : 'Server-side filtering failed';
678
+ return createFailureResult([], ServiceErrorCodes.FILTER_FAILED, errorMsg, {
679
+ metadata: { duration: Date.now() - startTime },
680
+ });
681
+ }
682
+ // CLI-3085: server-side filter-objects endpoint does not honor
683
+ // excludeSystemObjects for __mdt (and parity for History/Share/Feed/ChangeEvent
684
+ // /b/e/x suffixes is not guaranteed). Apply a name-based safety filter on the
685
+ // REST response when the caller requested system-object exclusion so the
686
+ // create flow stays tight regardless of server behavior.
687
+ // Support both `results` (plural) and `result` (singular) — different ISV
688
+ // endpoint versions use different keys.
689
+ let results = response.results ?? response.result ?? [];
690
+ if (options.excludeSystemObjects) {
691
+ const before = results.length;
692
+ results = results.filter((obj) => !NON_DATA_SUFFIX_PATTERN.test(obj.name));
693
+ if (results.length !== before) {
694
+ this.logger?.log(`REST post-filter excluded ${before - results.length} non-data objects (CLI-3085)`);
695
+ }
696
+ }
697
+ // CLI-3077: populate recordCount on the server response — older server builds
698
+ // skip count population unless withRecords/withoutRecords is set, which would
699
+ // otherwise surface as the "0 records" symptom. The server-side fix on
700
+ // packaging/v4.12.0 also populates unconditionally; this client-side step is
701
+ // defense-in-depth that lets the CLI ship independently of the package release.
702
+ const countsRequired = options.withRecords === true || options.withoutRecords === true;
703
+ const populated = results.some((obj) => obj.recordCount !== undefined && obj.recordCount !== null)
704
+ ? results
705
+ : await this.populateRecordCounts(results, countsRequired);
706
+ return createSuccessResult(populated, {
707
+ message: `Filtered ${String(populated.length)} objects via REST API`,
708
+ metadata: { duration: Date.now() - startTime, strategyUsed: 'rest-api' },
709
+ });
710
+ }
711
+ async getCustomerObjects() {
712
+ if (this.customerObjectCache !== null) {
713
+ return this.customerObjectCache;
714
+ }
715
+ // EntityDefinition is a Setup object backed by metadata, not records. The
716
+ // platform returns it in batches and does NOT support queryMore() — the
717
+ // query MUST resolve in a single batch. Salesforce caps the EntityDefinition
718
+ // batch at 200 rows; using a larger LIMIT triggers the runtime error
719
+ // "EntityDefinition does not support queryMore()". 200 covers all practical
720
+ // orgs; objects beyond 200 customer-facing entities are classified as
721
+ // internal (false-negative is acceptable for the long-tail).
722
+ //
723
+ // Chained .where() calls must use andWhere() for subsequent conditions —
724
+ // .where() replaces the first condition each time it's called.
725
+ const soql = CuneiformQueryBuilder.create()
726
+ .select(['QualifiedApiName'])
727
+ .from('EntityDefinition')
728
+ .where('IsCustomizable', '=', true)
729
+ .andWhere('IsLayoutable', '=', true)
730
+ .andWhere('IsDeprecatedAndHidden', '=', false)
731
+ .limit(200)
732
+ .toSOQL();
733
+ const result = await this.soqlAdapter.query(soql);
734
+ if (result.success) {
735
+ this.customerObjectCache = new Set(result.data.records.map((r) => r.QualifiedApiName));
736
+ }
737
+ else {
738
+ const errorMessage = `EntityDefinition classification query failed: ${result.message ?? 'unknown error'}`;
739
+ this.logger?.log(errorMessage);
740
+ throw new Error(errorMessage);
741
+ }
742
+ return this.customerObjectCache;
743
+ }
744
+ /**
745
+ * Applies classification filter to objects using EntityDefinition metadata.
746
+ * Customer-facing objects are those present in the EntityDefinition customer set.
747
+ * Internal objects are everything else.
748
+ */
749
+ async applyClassificationFilter(objects, classification) {
750
+ const customerObjects = await this.getCustomerObjects();
751
+ if (classification === 'customer') {
752
+ return objects.filter((obj) => customerObjects.has(obj.name));
753
+ }
754
+ // internal: NOT in customer set
755
+ return objects.filter((obj) => !customerObjects.has(obj.name));
756
+ }
757
+ /**
758
+ * Populates `recordCount` on every result via a single bulk record-count REST call.
759
+ *
760
+ * Always called during {@link filter} so the Records column is populated
761
+ * unconditionally — see CLI-3077.
762
+ *
763
+ * Failure semantics: when `required` is true (user passed `withRecords` or
764
+ * `withoutRecords`), a count-query failure throws so {@link filter} returns a
765
+ * `FILTER_FAILED` ServiceResult — we can't honestly filter by record count if
766
+ * we don't know counts. When `required` is false, a failure is logged and
767
+ * `recordCount` is left undefined; the display renders that as `—` rather than
768
+ * a misleading `0`.
769
+ *
770
+ * @param objects - SObjectInfo array to enrich with record counts
771
+ * @param required - Whether the caller's filter chain depends on accurate counts
772
+ * @returns Same array with `recordCount` populated (or unchanged on soft-failure)
773
+ * @throws Error when `required` is true and the count query fails
774
+ */
775
+ async populateRecordCounts(objects, required) {
776
+ if (objects.length === 0) {
777
+ return objects;
778
+ }
779
+ const objectNames = objects.map((obj) => obj.name);
780
+ const countsResult = await this.restApiAdapter.getRecordCounts(objectNames);
781
+ if (!countsResult.success) {
782
+ const message = `Record count query failed: ${countsResult.message ?? 'unknown error'}`;
783
+ this.logger?.log(message);
784
+ if (required) {
785
+ throw new Error(message);
786
+ }
787
+ return objects;
788
+ }
789
+ const counts = countsResult.data;
790
+ return objects.map((obj) => ({ ...obj, recordCount: counts.get(obj.name) ?? 0 }));
791
+ }
792
+ /**
793
+ * Applies hasRecordTypes filter by querying active record types.
794
+ * Uses lazy-loaded cache for record type information.
795
+ */
796
+ async applyHasRecordTypesFilter(objects) {
797
+ const recordTypeObjects = await this.getRecordTypeObjects();
798
+ return objects.filter((obj) => recordTypeObjects.has(obj.name)).map((obj) => ({ ...obj, hasRecordTypes: true }));
799
+ }
800
+ /**
801
+ * Lazily loads and caches the set of object names that have active record types.
802
+ *
803
+ * @returns Set of object API names with active record types
804
+ */
805
+ async getRecordTypeObjects() {
806
+ if (this.recordTypeCache !== null) {
807
+ return this.recordTypeCache;
808
+ }
809
+ const soql = CuneiformQueryBuilder.create()
810
+ .select(['SobjectType'])
811
+ .from('RecordType')
812
+ .where('IsActive', '=', true)
813
+ .groupBy(['SobjectType'])
814
+ .toSOQL();
815
+ const result = await this.soqlAdapter.query(soql);
816
+ if (result.success) {
817
+ this.recordTypeCache = new Set(result.data.records.map((r) => r.SobjectType));
818
+ }
819
+ else {
820
+ this.logger?.log(`Record type query failed: ${result.message ?? 'unknown error'}`);
821
+ this.recordTypeCache = new Set();
822
+ }
823
+ return this.recordTypeCache;
824
+ }
825
+ /**
826
+ * Applies withOwner filter by checking if objects have an OwnerId field.
827
+ * Uses cached describe results for efficiency.
828
+ */
829
+ async applyWithOwnerFilter(objects) {
830
+ const results = [];
831
+ // Check owner fields in parallel
832
+ const ownerPromises = objects.map(async (obj) => {
833
+ const hasOwner = await this.hasOwnerField(obj.name);
834
+ if (hasOwner) {
835
+ return { ...obj, hasOwner: true };
836
+ }
837
+ return null;
838
+ });
839
+ const resolved = await Promise.all(ownerPromises);
840
+ for (const item of resolved) {
841
+ if (item !== null) {
842
+ results.push(item);
843
+ }
844
+ }
845
+ return results;
846
+ }
847
+ /**
848
+ * Checks if an object has an OwnerId field.
849
+ * Results are cached per-session for efficiency.
850
+ *
851
+ * @param objectName - The object API name to check
852
+ * @returns True if the object has an OwnerId field
853
+ */
854
+ async hasOwnerField(objectName) {
855
+ // Check cache first
856
+ if (this.ownerFieldCache.has(objectName)) {
857
+ return this.ownerFieldCache.get(objectName);
858
+ }
859
+ try {
860
+ const describeResult = await this.restApiAdapter.describeObject(objectName);
861
+ if (!describeResult.success) {
862
+ this.logger?.log(`Describe failed for ${objectName}: ${describeResult.message ?? 'unknown error'}`);
863
+ this.ownerFieldCache.set(objectName, false);
864
+ return false;
865
+ }
866
+ const hasOwner = describeResult.data.fields.some((field) => field.name === 'OwnerId');
867
+ this.ownerFieldCache.set(objectName, hasOwner);
868
+ return hasOwner;
869
+ }
870
+ catch (error) {
871
+ const errorMessage = error instanceof Error ? error.message : String(error);
872
+ this.logger?.log(`Error checking owner field for ${objectName}: ${errorMessage}`);
873
+ this.ownerFieldCache.set(objectName, false);
874
+ return false;
875
+ }
876
+ }
877
+ }
878
+ //# sourceMappingURL=ObjectFilteringService.js.map