@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,981 @@
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 { createSuccessResult, createFailureResult } from '../models/service-result.js';
9
+ import { ServiceErrorCodes } from '../adapters/errors.js';
10
+ import { CuneiformQueryBuilder } from '../adapters/soql/cuneiform-query-builder.js';
11
+ import { validateSalesforceId, validateObjectName, validateNamespace, validatePagination, validateRequiredString, } from './validation.js';
12
+ import { MAX_PAGINATION_LIMIT } from './constants.js';
13
+ /**
14
+ * Default pagination limit for listDefinitions.
15
+ * Distinct from the general DEFAULT_PAGINATION_LIMIT (50) used by getDefinitions.
16
+ */
17
+ const LIST_DEFAULT_LIMIT = 25;
18
+ /** Empty/zero ListSummary used for failure-path returns. */
19
+ const EMPTY_LIST_SUMMARY = {
20
+ activeCount: 0,
21
+ inactiveCount: 0,
22
+ profiledCount: 0,
23
+ notProfiledCount: 0,
24
+ };
25
+ /**
26
+ * Maps a listDefinitions sort field to the corresponding Salesforce field API name.
27
+ */
28
+ const SORT_FIELD_MAP = {
29
+ key: 'Name',
30
+ name: 'pnova__Prop_Name__c',
31
+ objectName: 'pnova__Prop_SObjectApiName__c',
32
+ lastProfiledDate: 'pnova__PFx_LastDateProfiled__c',
33
+ };
34
+ /**
35
+ * SOQL field list for Profiling_Definition__c queries.
36
+ * Field names match actual Salesforce schema.
37
+ */
38
+ // Query building, validation, and constants extracted to DefinitionQueryBuilder
39
+ import { DefinitionQueryBuilder, DEFINITION_FIELDS } from './DefinitionQueryBuilder.js';
40
+ /**
41
+ * Domain service for querying Cuneiform profiling definitions.
42
+ *
43
+ * Provides methods to retrieve profiling definitions from the
44
+ * Profiling_Definition__c custom object with filtering and pagination.
45
+ *
46
+ * @design
47
+ * **Read-Only Service**: This service only queries definitions; it does not
48
+ * create or update them. Definition management is handled through the
49
+ * Cuneiform UI or separate admin operations.
50
+ *
51
+ * @design
52
+ * **Field Mapping**: Maps Salesforce custom field names (e.g., `Definition_Key__c`)
53
+ * to TypeScript-friendly camelCase (e.g., `key`). This isolates consumers from
54
+ * Salesforce naming conventions and enables cleaner TypeScript interfaces.
55
+ *
56
+ * @design
57
+ * **Validation Strategy**: Validates filter parameters (type, status, objectName)
58
+ * before building SOQL to fail fast with clear error messages rather than
59
+ * letting Salesforce return cryptic query errors.
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * const service = new ProfilingDefinitionService({ soqlAdapter });
64
+ * const result = await service.getDefinitions({ objectName: 'Account', isActive: true });
65
+ * if (result.success) {
66
+ * result.data.forEach(def => console.log(def.name));
67
+ * }
68
+ * ```
69
+ */
70
+ // NOTE: GlobalProfilingServiceResponse type and DEFINITION_RESPONSE_MARKER removed
71
+ // during REST API migration (CLI-1150). Apex routing now uses REST endpoints.
72
+ /**
73
+ * Base path for Cuneiform profiling REST API endpoints.
74
+ */
75
+ // Apex urlMapping is '/v1/profiling/*' — Salesforce auto-prepends namespace (pnova),
76
+ // so the actual URL is /services/apexrest/pnova/v1/profiling/*
77
+ const PROFILING_DEFINITION_REST_BASE = '/services/apexrest/pnova/v1/profiling';
78
+ export class ProfilingDefinitionService {
79
+ soqlAdapter;
80
+ restAdapter;
81
+ logger;
82
+ constructor(config) {
83
+ this.soqlAdapter = config.soqlAdapter;
84
+ this.restAdapter = config.restAdapter;
85
+ this.logger = config.logger;
86
+ }
87
+ /**
88
+ * Derives the definition type from boolean flags.
89
+ *
90
+ * Logic:
91
+ * - comparative: isFilteredSetB is true (comparing two data sets)
92
+ * - metadata: isMetadataOnly is true (metadata-only profiling)
93
+ * - historical: default (standard profiling)
94
+ *
95
+ * @param isFilteredSetB - Whether Set B is filtered
96
+ * @param isMetadataOnly - Whether metadata-only profiling
97
+ * @returns The derived definition type
98
+ */
99
+ static deriveDefinitionType(isFilteredSetB, isMetadataOnly) {
100
+ if (isFilteredSetB) {
101
+ return 'comparative';
102
+ }
103
+ if (isMetadataOnly) {
104
+ return 'metadata';
105
+ }
106
+ return 'historical';
107
+ }
108
+ /**
109
+ * Maps a raw Salesforce Profiling_Definition__c record to a ProfilingDefinition.
110
+ *
111
+ * @param record - The raw SOQL query result record
112
+ * @returns Mapped ProfilingDefinition with camelCase field names
113
+ */
114
+ static mapToProfilingDefinition(record) {
115
+ const isFilteredSetB = record.pnova__Prop_IsFiltered_SetB__c ?? false;
116
+ const isMetadataOnly = record.pnova__PropFx_IsMetadataProfilingOnly__c ?? false;
117
+ return {
118
+ id: record.Id,
119
+ key: record.Name,
120
+ name: record.pnova__Prop_Name__c,
121
+ objectName: record.pnova__Prop_SObjectApiName__c,
122
+ objectLabel: record.pnova__Prop_SObjectLabel__c ?? undefined,
123
+ type: ProfilingDefinitionService.deriveDefinitionType(isFilteredSetB, isMetadataOnly),
124
+ status: record.pnova__Agg_Status__c ?? 'NOT PROFILED',
125
+ category: record.pnova__Prop_Category__c ?? undefined,
126
+ description: record.pnova__Prop_Description__c ?? undefined,
127
+ isActive: record.pnova__Prop_IsActive__c ?? false,
128
+ isFilteredSetA: record.pnova__Prop_IsFiltered_SetA__c ?? false,
129
+ isFilteredSetB,
130
+ isMetadataOnly,
131
+ isProfilingAllRecords: record.pnova__PropFx_IsProfilingAllRecords__c ?? false,
132
+ hasRelatedSummaries: record.pnova__PFx_HasRelatedSummaries__c ?? false,
133
+ lastProfiledDate: record.pnova__PFx_LastDateProfiled__c ?? undefined,
134
+ timeCategory: record.pnova__Prop_TimeCategory__c ?? undefined,
135
+ segmentCategory: record.pnova__Prop_SegmentCategory__c ?? undefined,
136
+ createdDate: record.CreatedDate ?? undefined,
137
+ lastModifiedDate: record.LastModifiedDate ?? undefined,
138
+ };
139
+ }
140
+ /**
141
+ * Builds a complete SOQL query string for Profiling_Definition__c using CuneiformQueryBuilder.
142
+ *
143
+ * Type filtering is pushed to SOQL using the underlying boolean fields:
144
+ * - comparative: isFilteredSetB = true
145
+ * - metadata: isMetadataOnly = true AND isFilteredSetB = false
146
+ * - historical: isMetadataOnly = false AND isFilteredSetB = false
147
+ *
148
+ * @param options - The filter and pagination options
149
+ * @returns Complete SOQL query string
150
+ */
151
+ // Static query building methods delegated to DefinitionQueryBuilder
152
+ static buildSoqlQuery(options) {
153
+ return DefinitionQueryBuilder.buildSoqlQuery(options);
154
+ }
155
+ static validateType(type) {
156
+ return DefinitionQueryBuilder.validateType(type);
157
+ }
158
+ static validateStatus(status) {
159
+ return DefinitionQueryBuilder.validateStatus(status);
160
+ }
161
+ static buildCreateDefinitionRequestBody(input) {
162
+ return DefinitionQueryBuilder.buildCreateDefinitionRequestBody(input);
163
+ }
164
+ static buildListWhereConditions(filter) {
165
+ return DefinitionQueryBuilder.buildListWhereConditions(filter);
166
+ }
167
+ static applyWhereConditions(builder, conditions) {
168
+ DefinitionQueryBuilder.applyWhereConditions(builder, conditions);
169
+ }
170
+ /**
171
+ * Folds aggregate rows from the GROUP BY query into a totalCount and named
172
+ * bucket counts. Status taxonomy preserves the prior in-memory display logic:
173
+ * profiledCount covers SUCCESS and COMPLETE w/ FAILURES; notProfiledCount
174
+ * covers NOT PROFILED and ERROR; IN PROGRESS and null statuses contribute to
175
+ * totalCount and the active/inactive split but are excluded from
176
+ * profiled/notProfiled.
177
+ */
178
+ static foldAggregateRows(rows) {
179
+ const summary = { activeCount: 0, inactiveCount: 0, profiledCount: 0, notProfiledCount: 0 };
180
+ let totalCount = 0;
181
+ for (const row of rows) {
182
+ const cnt = row.cnt;
183
+ totalCount += cnt;
184
+ if (row.pnova__Prop_IsActive__c) {
185
+ summary.activeCount += cnt;
186
+ }
187
+ else {
188
+ summary.inactiveCount += cnt;
189
+ }
190
+ const status = row.pnova__Agg_Status__c;
191
+ if (status === 'SUCCESS' || status === 'COMPLETE w/ FAILURES') {
192
+ summary.profiledCount += cnt;
193
+ }
194
+ else if (status === 'NOT PROFILED' || status === 'ERROR') {
195
+ summary.notProfiledCount += cnt;
196
+ }
197
+ }
198
+ return { totalCount, summary };
199
+ }
200
+ /**
201
+ * Retrieves profiling definitions with optional filtering and pagination.
202
+ *
203
+ * Note: Type filtering is applied client-side after the query since the type
204
+ * is derived from boolean flags (Prop_IsFiltered_SetB__c, PropFx_IsMetadataProfilingOnly__c).
205
+ *
206
+ * @param options - Filter and pagination options
207
+ * @returns ServiceResult containing an array of ProfilingDefinition records
208
+ */
209
+ async getDefinitions(options = {}) {
210
+ const startTime = Date.now();
211
+ const emptyResult = [];
212
+ // Validate type filter if provided
213
+ if (options.type !== undefined) {
214
+ const typeError = ProfilingDefinitionService.validateType(options.type);
215
+ if (typeError) {
216
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, typeError, {
217
+ metadata: { duration: Date.now() - startTime },
218
+ });
219
+ }
220
+ }
221
+ // Validate status filter if provided
222
+ if (options.status !== undefined) {
223
+ const statusError = ProfilingDefinitionService.validateStatus(options.status);
224
+ if (statusError) {
225
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, statusError, {
226
+ metadata: { duration: Date.now() - startTime },
227
+ });
228
+ }
229
+ }
230
+ // Validate objectNames filter if provided (takes precedence over objectName)
231
+ if (options.objectNames !== undefined) {
232
+ for (const name of options.objectNames) {
233
+ const objectNameError = validateObjectName(name);
234
+ if (objectNameError) {
235
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_OBJECT_NAME, objectNameError, {
236
+ metadata: { duration: Date.now() - startTime },
237
+ });
238
+ }
239
+ }
240
+ }
241
+ // Validate objectName filter if provided
242
+ if (options.objectName !== undefined) {
243
+ const objectNameError = validateObjectName(options.objectName);
244
+ if (objectNameError) {
245
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_OBJECT_NAME, objectNameError, {
246
+ metadata: { duration: Date.now() - startTime },
247
+ });
248
+ }
249
+ }
250
+ // Validate pagination
251
+ const paginationError = validatePagination(options.limit, options.offset, MAX_PAGINATION_LIMIT);
252
+ if (paginationError) {
253
+ return createFailureResult(emptyResult, ServiceErrorCodes.INVALID_PAGINATION, paginationError, {
254
+ metadata: { duration: Date.now() - startTime },
255
+ });
256
+ }
257
+ try {
258
+ const soql = ProfilingDefinitionService.buildSoqlQuery(options);
259
+ this.logger?.log(`Querying profiling definitions: ${soql}`);
260
+ const queryResult = await this.soqlAdapter.query(soql);
261
+ if (!queryResult.success) {
262
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition query failed', { metadata: { duration: Date.now() - startTime } });
263
+ }
264
+ const definitions = queryResult.data.records.map((record) => ProfilingDefinitionService.mapToProfilingDefinition(record));
265
+ // Note: Type filtering is now done in SOQL via underlying boolean fields.
266
+ // No client-side filtering needed since SOQL already applied the filter.
267
+ const duration = Date.now() - startTime;
268
+ this.logger?.log(`Found ${String(definitions.length)} profiling definitions`);
269
+ return createSuccessResult(definitions, {
270
+ message: `Found ${String(definitions.length)} profiling definitions`,
271
+ metadata: { duration },
272
+ });
273
+ }
274
+ catch (error) {
275
+ const errorMessage = error instanceof Error ? error.message : String(error);
276
+ this.logger?.log(`Profiling definition query failed: ${errorMessage}`);
277
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
278
+ metadata: { duration: Date.now() - startTime },
279
+ });
280
+ }
281
+ }
282
+ /**
283
+ * Retrieves all profiling definitions matching the given filters, with automatic pagination.
284
+ *
285
+ * Fetches pages of MAX_PAGINATION_LIMIT (200) until a short page is returned.
286
+ * The limit and offset options are ignored — pagination is handled internally.
287
+ *
288
+ * @param options - Filter options (limit/offset are overridden)
289
+ * @returns ServiceResult containing all matching ProfilingDefinition records
290
+ */
291
+ async getAllDefinitions(options = {}) {
292
+ const startTime = Date.now();
293
+ const allDefinitions = [];
294
+ let offset = 0;
295
+ const pageSize = MAX_PAGINATION_LIMIT;
296
+ // eslint-disable-next-line no-constant-condition -- Pagination loop exits on short page or failure
297
+ while (true) {
298
+ // eslint-disable-next-line no-await-in-loop -- Sequential pagination: each page depends on knowing if more exist
299
+ const pageResult = await this.getDefinitions({ ...options, limit: pageSize, offset });
300
+ if (!pageResult.success) {
301
+ if (allDefinitions.length > 0) {
302
+ this.logger?.log(`Pagination failed at offset ${offset}, using ${allDefinitions.length} definitions fetched so far`);
303
+ return createSuccessResult(allDefinitions, {
304
+ warnings: [`Pagination incomplete: failed at offset ${offset}. Results may be partial.`],
305
+ metadata: { duration: Date.now() - startTime },
306
+ });
307
+ }
308
+ return pageResult;
309
+ }
310
+ allDefinitions.push(...pageResult.data);
311
+ if (pageResult.data.length < pageSize) {
312
+ break;
313
+ }
314
+ offset += pageSize;
315
+ }
316
+ this.logger?.log(`Fetched ${allDefinitions.length} total definitions across pagination`);
317
+ return createSuccessResult(allDefinitions, {
318
+ message: `Found ${allDefinitions.length} definitions`,
319
+ metadata: { duration: Date.now() - startTime },
320
+ });
321
+ }
322
+ /**
323
+ * Lists profiling definitions with filtering, pagination, and sorting.
324
+ *
325
+ * Executes two SOQL queries:
326
+ *
327
+ * - An aggregate GROUP BY query over the full filter set (no pagination) that
328
+ * yields totalCount and per-status / per-active bucket counts in one round-trip.
329
+ * - A data query with SELECT, WHERE, ORDER BY, LIMIT, OFFSET for the page.
330
+ *
331
+ * @param options - Filter, pagination, and sort options
332
+ * @returns ServiceResult containing definitions, totalCount, and aggregate summary
333
+ */
334
+ async listDefinitions(options) {
335
+ const startTime = Date.now();
336
+ const emptyResult = {
337
+ definitions: [],
338
+ totalCount: 0,
339
+ summary: { ...EMPTY_LIST_SUMMARY },
340
+ };
341
+ // Validate pagination
342
+ const limit = options.pagination?.limit ?? LIST_DEFAULT_LIMIT;
343
+ const offset = options.pagination?.offset ?? 0;
344
+ const paginationError = validatePagination(limit, offset, MAX_PAGINATION_LIMIT);
345
+ if (paginationError) {
346
+ return createFailureResult(emptyResult, ServiceErrorCodes.INVALID_PAGINATION, paginationError, {
347
+ metadata: { duration: Date.now() - startTime },
348
+ });
349
+ }
350
+ // Validate objects filter if provided
351
+ if (options.filter?.objects !== undefined) {
352
+ for (const name of options.filter.objects) {
353
+ const objectNameError = validateObjectName(name);
354
+ if (objectNameError) {
355
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_OBJECT_NAME, objectNameError, {
356
+ metadata: { duration: Date.now() - startTime },
357
+ });
358
+ }
359
+ }
360
+ }
361
+ // Validate namespace filter if provided
362
+ if (options.filter?.namespace !== undefined) {
363
+ const namespaceError = validateNamespace(options.filter.namespace);
364
+ if (namespaceError) {
365
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, namespaceError, {
366
+ metadata: { duration: Date.now() - startTime },
367
+ });
368
+ }
369
+ }
370
+ try {
371
+ // Build WHERE conditions (shared by both aggregate and data queries)
372
+ const whereBuilder = ProfilingDefinitionService.buildListWhereConditions(options.filter);
373
+ // 1. Aggregate GROUP BY query for totalCount AND summary buckets
374
+ const aggregateBuilder = new CuneiformQueryBuilder()
375
+ .select(['COUNT(Id) cnt', 'pnova__Agg_Status__c', 'pnova__Prop_IsActive__c'])
376
+ .from('pnova__Profiling_Definition__c');
377
+ ProfilingDefinitionService.applyWhereConditions(aggregateBuilder, whereBuilder);
378
+ aggregateBuilder.groupBy(['pnova__Agg_Status__c', 'pnova__Prop_IsActive__c']);
379
+ const aggregateSoql = aggregateBuilder.toSOQL();
380
+ this.logger?.log(`Aggregating profiling definitions: ${aggregateSoql}`);
381
+ const aggregateResult = await this.soqlAdapter.query(aggregateSoql);
382
+ if (!aggregateResult.success) {
383
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, aggregateResult.message ?? 'Profiling definition aggregate query failed', { metadata: { duration: Date.now() - startTime } });
384
+ }
385
+ const { totalCount, summary } = ProfilingDefinitionService.foldAggregateRows(aggregateResult.data.records);
386
+ // 2. Data query with pagination and sort
387
+ const dataBuilder = new CuneiformQueryBuilder()
388
+ .select(DEFINITION_FIELDS.split(', '))
389
+ .from('pnova__Profiling_Definition__c');
390
+ ProfilingDefinitionService.applyWhereConditions(dataBuilder, whereBuilder);
391
+ // Sort
392
+ const sortField = options.sort?.field ?? 'name';
393
+ const sortDirection = (options.sort?.direction ?? 'asc').toUpperCase();
394
+ const soqlSortField = SORT_FIELD_MAP[sortField] ?? 'pnova__Prop_Name__c';
395
+ if (sortField === 'lastProfiledDate') {
396
+ dataBuilder.orderBy(soqlSortField, sortDirection, 'NULLS LAST');
397
+ }
398
+ else {
399
+ dataBuilder.orderBy(soqlSortField, sortDirection);
400
+ }
401
+ dataBuilder.limit(limit);
402
+ dataBuilder.offset(offset);
403
+ const dataSoql = dataBuilder.toSOQL();
404
+ this.logger?.log(`Querying profiling definitions: ${dataSoql}`);
405
+ const queryResult = await this.soqlAdapter.query(dataSoql);
406
+ if (!queryResult.success) {
407
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition query failed', { metadata: { duration: Date.now() - startTime } });
408
+ }
409
+ const definitions = queryResult.data.records.map((record) => ProfilingDefinitionService.mapToProfilingDefinition(record));
410
+ const duration = Date.now() - startTime;
411
+ this.logger?.log(`Listed ${String(definitions.length)} of ${String(totalCount)} profiling definitions`);
412
+ return createSuccessResult({ definitions, totalCount, summary }, {
413
+ message: `Listed ${String(definitions.length)} of ${String(totalCount)} profiling definitions`,
414
+ metadata: { duration },
415
+ });
416
+ }
417
+ catch (error) {
418
+ const errorMessage = error instanceof Error ? error.message : String(error);
419
+ this.logger?.log(`Profiling definition list failed: ${errorMessage}`);
420
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
421
+ metadata: { duration: Date.now() - startTime },
422
+ });
423
+ }
424
+ }
425
+ /**
426
+ * Retrieves a single profiling definition by its Salesforce ID.
427
+ *
428
+ * @param id - The Salesforce record ID (15 or 18 characters)
429
+ * @returns ServiceResult containing the ProfilingDefinition or null if not found
430
+ */
431
+ async getDefinitionById(id) {
432
+ const startTime = Date.now();
433
+ const emptyResult = null;
434
+ // Validate ID format
435
+ const idError = validateSalesforceId(id);
436
+ if (idError) {
437
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_ID, idError, {
438
+ metadata: { duration: Date.now() - startTime },
439
+ });
440
+ }
441
+ try {
442
+ const soql = new CuneiformQueryBuilder()
443
+ .select(DEFINITION_FIELDS.split(', '))
444
+ .from('pnova__Profiling_Definition__c')
445
+ .where('Id', '=', id)
446
+ .limit(1)
447
+ .toSOQL();
448
+ this.logger?.log(`Querying profiling definition by ID: ${id}`);
449
+ const queryResult = await this.soqlAdapter.query(soql);
450
+ if (!queryResult.success) {
451
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition query failed', { metadata: { duration: Date.now() - startTime } });
452
+ }
453
+ const duration = Date.now() - startTime;
454
+ if (queryResult.data.records.length === 0) {
455
+ this.logger?.log(`Profiling definition not found: ${id}`);
456
+ return createSuccessResult(emptyResult, {
457
+ message: `Profiling definition not found: ${id}`,
458
+ warnings: [`No profiling definition found with ID: ${id}`],
459
+ metadata: { duration },
460
+ });
461
+ }
462
+ const definition = ProfilingDefinitionService.mapToProfilingDefinition(queryResult.data.records[0]);
463
+ this.logger?.log(`Found profiling definition: ${definition.name}`);
464
+ return createSuccessResult(definition, {
465
+ message: `Found profiling definition: ${definition.name}`,
466
+ metadata: { duration },
467
+ });
468
+ }
469
+ catch (error) {
470
+ const errorMessage = error instanceof Error ? error.message : String(error);
471
+ this.logger?.log(`Profiling definition query failed: ${errorMessage}`);
472
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
473
+ metadata: { duration: Date.now() - startTime },
474
+ });
475
+ }
476
+ }
477
+ /**
478
+ * Retrieves a single profiling definition by its definition key (e.g., "PD-0001").
479
+ *
480
+ * The key is stored in the standard Name field as an AutoNumber.
481
+ *
482
+ * @param key - The definition key (e.g., "PD-0001")
483
+ * @returns ServiceResult containing the ProfilingDefinition or null if not found
484
+ */
485
+ async getDefinitionByKey(key) {
486
+ const startTime = Date.now();
487
+ const emptyResult = null;
488
+ // Validate key is provided
489
+ const keyError = validateRequiredString(key, 'Definition key');
490
+ if (keyError) {
491
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, keyError, {
492
+ metadata: { duration: Date.now() - startTime },
493
+ });
494
+ }
495
+ try {
496
+ // Name is the standard AutoNumber field (format: PD-{0000})
497
+ const soql = new CuneiformQueryBuilder()
498
+ .select(DEFINITION_FIELDS.split(', '))
499
+ .from('pnova__Profiling_Definition__c')
500
+ .where('Name', '=', key.trim())
501
+ .limit(1)
502
+ .toSOQL();
503
+ this.logger?.log(`Querying profiling definition by key: ${key}`);
504
+ const queryResult = await this.soqlAdapter.query(soql);
505
+ if (!queryResult.success) {
506
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition query failed', { metadata: { duration: Date.now() - startTime } });
507
+ }
508
+ const duration = Date.now() - startTime;
509
+ if (queryResult.data.records.length === 0) {
510
+ this.logger?.log(`Profiling definition not found: ${key}`);
511
+ return createSuccessResult(emptyResult, {
512
+ message: `Profiling definition not found: ${key}`,
513
+ warnings: [`No profiling definition found with key: ${key}`],
514
+ metadata: { duration },
515
+ });
516
+ }
517
+ const definition = ProfilingDefinitionService.mapToProfilingDefinition(queryResult.data.records[0]);
518
+ this.logger?.log(`Found profiling definition: ${definition.name} (key: ${key})`);
519
+ return createSuccessResult(definition, {
520
+ message: `Found profiling definition: ${definition.name}`,
521
+ metadata: { duration },
522
+ });
523
+ }
524
+ catch (error) {
525
+ const errorMessage = error instanceof Error ? error.message : String(error);
526
+ this.logger?.log(`Profiling definition query failed: ${errorMessage}`);
527
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
528
+ metadata: { duration: Date.now() - startTime },
529
+ });
530
+ }
531
+ }
532
+ /**
533
+ * Retrieves multiple profiling definitions by their human-readable keys in a single SOQL query.
534
+ *
535
+ * Replaces the N+1 pattern of calling getDefinitionByKey() per key with a single
536
+ * `WHERE Name IN (...)` query. Returns a Map keyed by the requested key values.
537
+ *
538
+ * @param keys - Array of definition keys (e.g., ['PD-0001', 'PD-0002'])
539
+ * @returns ServiceResult containing a Map of key → ProfilingDefinition (missing keys have null)
540
+ */
541
+ async getDefinitionsByKeys(keys) {
542
+ const startTime = Date.now();
543
+ const emptyResult = new Map();
544
+ if (keys.length === 0) {
545
+ return createSuccessResult(emptyResult, {
546
+ message: 'No keys provided',
547
+ metadata: { duration: Date.now() - startTime },
548
+ });
549
+ }
550
+ try {
551
+ const trimmedKeys = keys.map((k) => k.trim());
552
+ const soql = new CuneiformQueryBuilder()
553
+ .select(DEFINITION_FIELDS.split(', '))
554
+ .from('pnova__Profiling_Definition__c')
555
+ .andWhereIn('Name', trimmedKeys)
556
+ .toSOQL();
557
+ this.logger?.log(`Querying profiling definitions by keys: ${trimmedKeys.join(', ')}`);
558
+ const queryResult = await this.soqlAdapter.query(soql);
559
+ if (!queryResult.success) {
560
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition batch query failed', { metadata: { duration: Date.now() - startTime } });
561
+ }
562
+ const duration = Date.now() - startTime;
563
+ // Build result map: key → definition or null
564
+ const resultMap = new Map();
565
+ const recordsByKey = new Map();
566
+ for (const record of queryResult.data.records) {
567
+ recordsByKey.set(record.Name, record);
568
+ }
569
+ for (const key of trimmedKeys) {
570
+ const record = recordsByKey.get(key);
571
+ resultMap.set(key, record ? ProfilingDefinitionService.mapToProfilingDefinition(record) : null);
572
+ }
573
+ const foundCount = queryResult.data.records.length;
574
+ this.logger?.log(`Found ${foundCount}/${trimmedKeys.length} profiling definitions`);
575
+ return createSuccessResult(resultMap, {
576
+ message: `Found ${foundCount} of ${trimmedKeys.length} requested definitions`,
577
+ metadata: { duration },
578
+ });
579
+ }
580
+ catch (error) {
581
+ const errorMessage = error instanceof Error ? error.message : String(error);
582
+ this.logger?.log(`Profiling definition batch query failed: ${errorMessage}`);
583
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
584
+ metadata: { duration: Date.now() - startTime },
585
+ });
586
+ }
587
+ }
588
+ /**
589
+ * Retrieves profiling definitions filtered by type.
590
+ *
591
+ * Convenience method that delegates to getDefinitions() with the type filter.
592
+ *
593
+ * @param type - The definition type to filter by
594
+ * @param options - Additional filter and pagination options
595
+ * @returns ServiceResult containing an array of ProfilingDefinition records
596
+ */
597
+ async getDefinitionsByType(type, options = {}) {
598
+ return this.getDefinitions({ ...options, type });
599
+ }
600
+ /**
601
+ * Retrieves profiling definitions filtered by status.
602
+ *
603
+ * Convenience method that delegates to getDefinitions() with the status filter.
604
+ *
605
+ * @param status - The profiling status to filter by
606
+ * @param options - Additional filter and pagination options
607
+ * @returns ServiceResult containing an array of ProfilingDefinition records
608
+ */
609
+ async getDefinitionsByStatus(status, options = {}) {
610
+ return this.getDefinitions({ ...options, status });
611
+ }
612
+ /**
613
+ * Creates a new profiling definition via the Cuneiform REST API.
614
+ *
615
+ * Definition creation is routed through the REST endpoint which enforces
616
+ * server-side permission checks in GlobalProfilingService.
617
+ *
618
+ * @param input - The definition input containing name, objectName, and optional fields
619
+ * @returns ServiceResult containing the created ProfilingDefinition or null on failure
620
+ */
621
+ async createDefinition(input) {
622
+ const startTime = Date.now();
623
+ const emptyResult = null;
624
+ if (!this.restAdapter) {
625
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'restAdapter is required for create operations.', { metadata: { duration: Date.now() - startTime } });
626
+ }
627
+ return this.createDefinitionViaRest(input, startTime);
628
+ }
629
+ /**
630
+ * Creates multiple profiling definitions via the Cuneiform REST API.
631
+ *
632
+ * Each definition is created individually since the REST endpoint
633
+ * currently supports single creation per request.
634
+ *
635
+ * @param inputs - Array of definition inputs (1-10 items)
636
+ * @returns ServiceResult containing succeeded and failed arrays
637
+ */
638
+ async createDefinitions(inputs) {
639
+ const startTime = Date.now();
640
+ const emptyResult = { succeeded: [], failed: [] };
641
+ if (!this.restAdapter) {
642
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'restAdapter is required for create operations.', { metadata: { duration: Date.now() - startTime } });
643
+ }
644
+ return this.createDefinitionsViaRest(inputs, startTime);
645
+ }
646
+ /**
647
+ * Updates metadata attributes on a profiling definition.
648
+ *
649
+ * Writes only the supplied attributes; untouched columns are preserved.
650
+ * At least one attribute must be provided.
651
+ *
652
+ * @param definitionId - The Salesforce record ID of the definition to update
653
+ * @param attributes - Partial attribute set to write
654
+ * @returns ServiceResult containing the update result
655
+ */
656
+ async updateAttributes(definitionId, attributes) {
657
+ const startTime = Date.now();
658
+ const emptyResult = { id: definitionId, updated: false, updatedAttributes: [] };
659
+ // Validate definition ID
660
+ const idError = validateSalesforceId(definitionId);
661
+ if (idError) {
662
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_ID, idError, {
663
+ metadata: { duration: Date.now() - startTime },
664
+ });
665
+ }
666
+ // Check that REST adapter is configured
667
+ if (!this.restAdapter) {
668
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_UPDATE_FAILED, 'REST adapter required for update operations', { metadata: { duration: Date.now() - startTime } });
669
+ }
670
+ // Build the partial update payload — only supplied attributes
671
+ // eslint-disable-next-line camelcase -- Salesforce custom field API names require this casing
672
+ const payload = {};
673
+ const updatedAttributes = [];
674
+ if (attributes.name !== undefined) {
675
+ // eslint-disable-next-line camelcase -- Salesforce custom field API name
676
+ payload.pnova__Prop_Name__c = attributes.name;
677
+ updatedAttributes.push('name');
678
+ }
679
+ if (attributes.category !== undefined) {
680
+ // eslint-disable-next-line camelcase -- Salesforce custom field API name
681
+ payload.pnova__Prop_Category__c = attributes.category;
682
+ updatedAttributes.push('category');
683
+ }
684
+ if (attributes.timeCategory !== undefined) {
685
+ // eslint-disable-next-line camelcase -- Salesforce custom field API name
686
+ payload.pnova__Prop_TimeCategory__c = attributes.timeCategory;
687
+ updatedAttributes.push('timeCategory');
688
+ }
689
+ if (attributes.segmentCategory !== undefined) {
690
+ // eslint-disable-next-line camelcase -- Salesforce custom field API name
691
+ payload.pnova__Prop_SegmentCategory__c = attributes.segmentCategory;
692
+ updatedAttributes.push('segmentCategory');
693
+ }
694
+ if (attributes.description !== undefined) {
695
+ // eslint-disable-next-line camelcase -- Salesforce custom field API name
696
+ payload.pnova__Prop_Description__c = attributes.description;
697
+ updatedAttributes.push('description');
698
+ }
699
+ try {
700
+ this.logger?.log(`Updating definition ${definitionId}: ${updatedAttributes.join(', ')}`);
701
+ const updateResult = await this.restAdapter.updateRecord('pnova__Profiling_Definition__c', definitionId, payload);
702
+ const duration = Date.now() - startTime;
703
+ if (!updateResult.success) {
704
+ this.logger?.log(`Definition attribute update failed: ${updateResult.message ?? 'Unknown error'}`);
705
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_UPDATE_FAILED, updateResult.message ?? 'Definition attribute update failed', { metadata: { duration } });
706
+ }
707
+ this.logger?.log(`Definition ${definitionId} attributes updated successfully`);
708
+ return createSuccessResult({ id: definitionId, updated: true, updatedAttributes }, {
709
+ message: `Updated definition attributes: ${updatedAttributes.join(', ')}`,
710
+ metadata: { duration },
711
+ });
712
+ }
713
+ catch (error) {
714
+ const errorMessage = error instanceof Error ? error.message : String(error);
715
+ this.logger?.log(`Definition attribute update failed: ${errorMessage}`);
716
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_UPDATE_FAILED, errorMessage, {
717
+ metadata: { duration: Date.now() - startTime },
718
+ });
719
+ }
720
+ }
721
+ /**
722
+ * Deletes profiling definitions by their Salesforce IDs.
723
+ *
724
+ * Safety checks are applied before deletion:
725
+ * - Definition must exist
726
+ * - Definition must have no associated summaries (hasRelatedSummaries field)
727
+ *
728
+ * Definitions can be deleted regardless of profiling status when no
729
+ * associated summaries exist.
730
+ *
731
+ * Definitions that fail safety checks are skipped with reasons provided.
732
+ *
733
+ * @param ids - Array of Salesforce record IDs to delete (1-200 items)
734
+ * @param options - Optional progress callback and configuration
735
+ * @returns ServiceResult containing deletion counts and skip/failure details
736
+ */
737
+ async deleteDefinitions(ids, options) {
738
+ const startTime = Date.now();
739
+ const emptyResult = {
740
+ deleted: 0,
741
+ skipped: 0,
742
+ failed: 0,
743
+ skipReasons: [],
744
+ failures: [],
745
+ };
746
+ // Validate ids array is not empty
747
+ if (ids.length === 0) {
748
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_DELETE_FAILED, 'Definition IDs array cannot be empty', { metadata: { duration: Date.now() - startTime } });
749
+ }
750
+ // Validate REST adapter is available
751
+ if (!this.restAdapter) {
752
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_DELETE_FAILED, 'REST adapter required for delete operations', { metadata: { duration: Date.now() - startTime } });
753
+ }
754
+ // Validate all IDs have valid format
755
+ for (const id of ids) {
756
+ const idError = validateSalesforceId(id);
757
+ if (idError) {
758
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_ID, `Invalid ID "${id}": ${idError}`, {
759
+ metadata: { duration: Date.now() - startTime },
760
+ });
761
+ }
762
+ }
763
+ const result = {
764
+ deleted: 0,
765
+ skipped: 0,
766
+ failed: 0,
767
+ skipReasons: [],
768
+ failures: [],
769
+ };
770
+ const total = ids.length;
771
+ let current = 0;
772
+ // Process each ID sequentially - intentional for safe deletion with proper error handling
773
+ // Each operation depends on the previous (safety checks before delete)
774
+ // eslint-disable-next-line no-await-in-loop -- Sequential processing for safe deletion with individual error handling
775
+ for (const id of ids) {
776
+ current++;
777
+ try {
778
+ // Look up the definition
779
+ // eslint-disable-next-line no-await-in-loop -- Sequential: must verify existence before deletion
780
+ const lookupResult = await this.getDefinitionById(id);
781
+ if (!lookupResult.success) {
782
+ result.failed++;
783
+ result.failures.push({
784
+ id,
785
+ error: lookupResult.message ?? 'Failed to lookup definition',
786
+ });
787
+ options?.onProgress?.({ id, name: id, status: 'failed', reason: 'lookup_failed', current, total });
788
+ continue;
789
+ }
790
+ // Check if definition exists
791
+ if (lookupResult.data === null) {
792
+ result.skipped++;
793
+ result.skipReasons.push({
794
+ id,
795
+ reason: 'not_found',
796
+ });
797
+ options?.onProgress?.({ id, name: id, status: 'skipped', reason: 'not_found', current, total });
798
+ continue;
799
+ }
800
+ const definition = lookupResult.data;
801
+ const defMeta = {
802
+ key: definition.key,
803
+ objectName: definition.objectName,
804
+ objectLabel: definition.objectLabel,
805
+ category: definition.category,
806
+ timeCategory: definition.timeCategory,
807
+ segmentCategory: definition.segmentCategory,
808
+ profilingStatus: definition.status,
809
+ };
810
+ // Safety check: Check for associated summaries
811
+ // Use hasRelatedSummaries field (formula field on the definition object)
812
+ const hasSummaries = definition.hasRelatedSummaries === true;
813
+ if (hasSummaries) {
814
+ result.skipped++;
815
+ result.skipReasons.push({
816
+ id,
817
+ name: definition.name,
818
+ reason: 'has_summaries',
819
+ });
820
+ options?.onProgress?.({
821
+ id,
822
+ ...defMeta,
823
+ name: definition.name,
824
+ status: 'skipped',
825
+ reason: 'has_summaries',
826
+ current,
827
+ total,
828
+ });
829
+ continue;
830
+ }
831
+ // All safety checks passed - delete the definition
832
+ // eslint-disable-next-line no-await-in-loop -- Sequential: dependent on prior safety checks passing
833
+ const deleteResult = await this.restAdapter.deleteRecord('pnova__Profiling_Definition__c', id);
834
+ if (!deleteResult.success) {
835
+ const deleteError = deleteResult.message ?? 'Failed to delete definition';
836
+ result.failed++;
837
+ result.failures.push({
838
+ id,
839
+ name: definition.name,
840
+ error: deleteError,
841
+ });
842
+ options?.onProgress?.({
843
+ id,
844
+ ...defMeta,
845
+ name: definition.name,
846
+ status: 'failed',
847
+ reason: deleteError,
848
+ current,
849
+ total,
850
+ });
851
+ continue;
852
+ }
853
+ result.deleted++;
854
+ this.logger?.log(`Deleted profiling definition: ${id}`);
855
+ options?.onProgress?.({ id, ...defMeta, name: definition.name, status: 'deleted', current, total });
856
+ }
857
+ catch (error) {
858
+ const errorMessage = error instanceof Error ? error.message : String(error);
859
+ result.failed++;
860
+ result.failures.push({
861
+ id,
862
+ error: errorMessage,
863
+ });
864
+ options?.onProgress?.({ id, name: id, status: 'failed', reason: errorMessage, current, total });
865
+ }
866
+ }
867
+ const duration = Date.now() - startTime;
868
+ const totalProcessed = result.deleted + result.skipped + result.failed;
869
+ const summaryMessage = `Deleted ${result.deleted}/${totalProcessed} definitions (${result.skipped} skipped, ${result.failed} failed)`;
870
+ this.logger?.log(summaryMessage);
871
+ return createSuccessResult(result, {
872
+ message: summaryMessage,
873
+ warnings: result.skipped > 0 || result.failed > 0 ? [`${result.skipped} skipped, ${result.failed} failed`] : undefined,
874
+ metadata: { duration },
875
+ });
876
+ }
877
+ // NOTE: createDefinitionViaApex and createDefinitionsViaApex removed during REST API migration (CLI-1150).
878
+ // These methods used anonymous Apex routing via GlobalProfilingService and have been replaced
879
+ // by createDefinitionViaRest and createDefinitionsViaRest.
880
+ /**
881
+ * Creates a single definition via the Cuneiform REST API.
882
+ */
883
+ async createDefinitionViaRest(input, startTime) {
884
+ const emptyResult = null;
885
+ // Validate objectName
886
+ const objectNameError = validateObjectName(input.objectName);
887
+ if (objectNameError) {
888
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_OBJECT_NAME, objectNameError, {
889
+ metadata: { duration: Date.now() - startTime },
890
+ });
891
+ }
892
+ try {
893
+ this.logger?.log(`Creating profiling definition for object: ${input.objectName}`);
894
+ const requestBody = ProfilingDefinitionService.buildCreateDefinitionRequestBody(input);
895
+ const restResult = await this.restAdapter.request({
896
+ url: `${PROFILING_DEFINITION_REST_BASE}/create-definition`,
897
+ method: 'POST',
898
+ body: requestBody,
899
+ });
900
+ if (!restResult.success) {
901
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, restResult.message ?? 'REST API call failed', { metadata: { duration: Date.now() - startTime } });
902
+ }
903
+ const response = restResult.data;
904
+ if (!response.success) {
905
+ const errorMsg = response.errors && response.errors.length > 0 ? response.errors.join('; ') : 'Definition creation failed';
906
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, errorMsg, {
907
+ metadata: { duration: Date.now() - startTime },
908
+ });
909
+ }
910
+ if (!response.results || response.results.length === 0) {
911
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'No results returned from profiling definition REST API', { metadata: { duration: Date.now() - startTime } });
912
+ }
913
+ const createdId = response.results[0].id;
914
+ this.logger?.log(`Created profiling definition with ID: ${createdId}`);
915
+ // Query back the full definition record
916
+ const queryResult = await this.getDefinitionById(createdId);
917
+ if (!queryResult.success || queryResult.data === null) {
918
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, queryResult.message ?? 'Failed to retrieve created definition', { metadata: { duration: Date.now() - startTime } });
919
+ }
920
+ const duration = Date.now() - startTime;
921
+ this.logger?.log(`Created profiling definition: ${queryResult.data.name} (${queryResult.data.key})`);
922
+ return createSuccessResult(queryResult.data, {
923
+ message: `Created profiling definition: ${queryResult.data.name}`,
924
+ metadata: { duration },
925
+ });
926
+ }
927
+ catch (error) {
928
+ const errorMessage = error instanceof Error ? error.message : String(error);
929
+ this.logger?.log(`Failed to create profiling definition: ${errorMessage}`);
930
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, errorMessage, {
931
+ metadata: { duration: Date.now() - startTime },
932
+ });
933
+ }
934
+ }
935
+ /**
936
+ * Creates multiple definitions via the Cuneiform REST API.
937
+ *
938
+ * The REST endpoint supports single creation, so definitions are created sequentially.
939
+ */
940
+ async createDefinitionsViaRest(inputs, startTime) {
941
+ const emptyResult = { succeeded: [], failed: [] };
942
+ if (inputs.length === 0) {
943
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'Inputs array must contain at least one definition.', { metadata: { duration: Date.now() - startTime } });
944
+ }
945
+ try {
946
+ this.logger?.log(`Creating ${inputs.length} profiling definitions via REST API`);
947
+ const succeeded = [];
948
+ const failed = [];
949
+ /* eslint-disable no-await-in-loop -- Sequential creation to avoid overwhelming the org */
950
+ for (const input of inputs) {
951
+ const result = await this.createDefinitionViaRest(input, Date.now());
952
+ if (result.success && result.data) {
953
+ succeeded.push(result.data);
954
+ }
955
+ else {
956
+ failed.push({
957
+ input,
958
+ error: result.message ?? 'Creation failed',
959
+ errorCode: result.errorCode ?? ServiceErrorCodes.DEFINITION_CREATE_FAILED,
960
+ });
961
+ }
962
+ }
963
+ /* eslint-enable no-await-in-loop */
964
+ const duration = Date.now() - startTime;
965
+ this.logger?.log(`Created ${succeeded.length}/${inputs.length} definitions (${failed.length} failed)`);
966
+ return createSuccessResult({ succeeded, failed }, {
967
+ message: `Created ${succeeded.length}/${inputs.length} definitions`,
968
+ warnings: failed.length > 0 ? [`${failed.length} definition(s) failed to create`] : undefined,
969
+ metadata: { duration },
970
+ });
971
+ }
972
+ catch (error) {
973
+ const errorMessage = error instanceof Error ? error.message : String(error);
974
+ this.logger?.log(`Bulk create operation failed: ${errorMessage}`);
975
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, errorMessage, {
976
+ metadata: { duration: Date.now() - startTime },
977
+ });
978
+ }
979
+ }
980
+ }
981
+ //# sourceMappingURL=ProfilingDefinitionService.js.map