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

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 (488) hide show
  1. package/LICENSE +81 -30
  2. package/README.md +168 -134
  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/lifecycle.d.ts +112 -0
  10. package/lib/adapters/lifecycle.js +94 -0
  11. package/lib/adapters/lifecycle.js.map +1 -0
  12. package/lib/adapters/rest/cache.d.ts +69 -0
  13. package/lib/adapters/rest/cache.js +133 -0
  14. package/lib/adapters/rest/cache.js.map +1 -0
  15. package/lib/adapters/rest/index.d.ts +11 -0
  16. package/lib/adapters/rest/index.js +18 -0
  17. package/lib/adapters/rest/index.js.map +1 -0
  18. package/lib/adapters/rest/profiling-rest-client.d.ts +137 -0
  19. package/lib/adapters/rest/profiling-rest-client.js +115 -0
  20. package/lib/adapters/rest/profiling-rest-client.js.map +1 -0
  21. package/lib/adapters/rest/rest-api-adapter.d.ts +393 -0
  22. package/lib/adapters/rest/rest-api-adapter.js +764 -0
  23. package/lib/adapters/rest/rest-api-adapter.js.map +1 -0
  24. package/lib/adapters/rest/types.d.ts +34 -0
  25. package/lib/adapters/rest/types.js +9 -0
  26. package/lib/adapters/rest/types.js.map +1 -0
  27. package/lib/adapters/retry.d.ts +91 -0
  28. package/lib/adapters/retry.js +215 -0
  29. package/lib/adapters/retry.js.map +1 -0
  30. package/lib/adapters/soql/cuneiform-query-builder.d.ts +418 -0
  31. package/lib/adapters/soql/cuneiform-query-builder.js +606 -0
  32. package/lib/adapters/soql/cuneiform-query-builder.js.map +1 -0
  33. package/lib/adapters/soql/soql-query-adapter.d.ts +141 -0
  34. package/lib/adapters/soql/soql-query-adapter.js +259 -0
  35. package/lib/adapters/soql/soql-query-adapter.js.map +1 -0
  36. package/lib/adapters/soql/types.d.ts +37 -0
  37. package/lib/adapters/soql/types.js +19 -0
  38. package/lib/adapters/soql/types.js.map +1 -0
  39. package/lib/adapters/testing/index.d.ts +37 -0
  40. package/lib/adapters/testing/index.js +20 -0
  41. package/lib/adapters/testing/index.js.map +1 -0
  42. package/lib/adapters/testing/mock-connection.d.ts +77 -0
  43. package/lib/adapters/testing/mock-connection.js +207 -0
  44. package/lib/adapters/testing/mock-connection.js.map +1 -0
  45. package/lib/adapters/testing/mock-logger.d.ts +29 -0
  46. package/lib/adapters/testing/mock-logger.js +57 -0
  47. package/lib/adapters/testing/mock-logger.js.map +1 -0
  48. package/lib/adapters/testing/mock-mcp-adapters.d.ts +32 -0
  49. package/lib/adapters/testing/mock-mcp-adapters.js +52 -0
  50. package/lib/adapters/testing/mock-mcp-adapters.js.map +1 -0
  51. package/lib/adapters/testing/mock-oclif-config.d.ts +22 -0
  52. package/lib/adapters/testing/mock-oclif-config.js +90 -0
  53. package/lib/adapters/testing/mock-oclif-config.js.map +1 -0
  54. package/lib/adapters/testing/mock-rest-adapter.d.ts +26 -0
  55. package/lib/adapters/testing/mock-rest-adapter.js +243 -0
  56. package/lib/adapters/testing/mock-rest-adapter.js.map +1 -0
  57. package/lib/adapters/testing/mock-salesforce-connection.d.ts +40 -0
  58. package/lib/adapters/testing/mock-salesforce-connection.js +61 -0
  59. package/lib/adapters/testing/mock-salesforce-connection.js.map +1 -0
  60. package/lib/adapters/testing/mock-soql-adapter.d.ts +30 -0
  61. package/lib/adapters/testing/mock-soql-adapter.js +120 -0
  62. package/lib/adapters/testing/mock-soql-adapter.js.map +1 -0
  63. package/lib/adapters/testing/mock-tooling-adapter.d.ts +24 -0
  64. package/lib/adapters/testing/mock-tooling-adapter.js +163 -0
  65. package/lib/adapters/testing/mock-tooling-adapter.js.map +1 -0
  66. package/lib/adapters/testing/stub-connection.d.ts +93 -0
  67. package/lib/adapters/testing/stub-connection.js +97 -0
  68. package/lib/adapters/testing/stub-connection.js.map +1 -0
  69. package/lib/adapters/testing/stub-rest-adapter.d.ts +52 -0
  70. package/lib/adapters/testing/stub-rest-adapter.js +58 -0
  71. package/lib/adapters/testing/stub-rest-adapter.js.map +1 -0
  72. package/lib/adapters/testing/stub-soql-adapter.d.ts +56 -0
  73. package/lib/adapters/testing/stub-soql-adapter.js +50 -0
  74. package/lib/adapters/testing/stub-soql-adapter.js.map +1 -0
  75. package/lib/adapters/testing/types.d.ts +71 -0
  76. package/lib/adapters/testing/types.js +9 -0
  77. package/lib/adapters/testing/types.js.map +1 -0
  78. package/lib/adapters/tooling/index.d.ts +10 -0
  79. package/lib/adapters/tooling/index.js +17 -0
  80. package/lib/adapters/tooling/index.js.map +1 -0
  81. package/lib/adapters/tooling/tooling-api-adapter.d.ts +157 -0
  82. package/lib/adapters/tooling/tooling-api-adapter.js +339 -0
  83. package/lib/adapters/tooling/tooling-api-adapter.js.map +1 -0
  84. package/lib/adapters/tooling/types.d.ts +81 -0
  85. package/lib/adapters/tooling/types.js +9 -0
  86. package/lib/adapters/tooling/types.js.map +1 -0
  87. package/lib/adapters/types.d.ts +112 -0
  88. package/lib/adapters/types.js +169 -0
  89. package/lib/adapters/types.js.map +1 -0
  90. package/lib/base/cuneiform-command.d.ts +175 -0
  91. package/lib/base/cuneiform-command.js +326 -0
  92. package/lib/base/cuneiform-command.js.map +1 -0
  93. package/lib/commands/cuneiform/compatibility/check.d.ts +43 -0
  94. package/lib/commands/cuneiform/compatibility/check.js +114 -0
  95. package/lib/commands/cuneiform/compatibility/check.js.map +1 -0
  96. package/lib/commands/cuneiform/definition/create.d.ts +120 -0
  97. package/lib/commands/cuneiform/definition/create.js +737 -0
  98. package/lib/commands/cuneiform/definition/create.js.map +1 -0
  99. package/lib/commands/cuneiform/definition/export.d.ts +57 -0
  100. package/lib/commands/cuneiform/definition/export.js +133 -0
  101. package/lib/commands/cuneiform/definition/export.js.map +1 -0
  102. package/lib/commands/cuneiform/definition/get.d.ts +86 -0
  103. package/lib/commands/cuneiform/definition/get.js +277 -0
  104. package/lib/commands/cuneiform/definition/get.js.map +1 -0
  105. package/lib/commands/cuneiform/definition/import.d.ts +54 -0
  106. package/lib/commands/cuneiform/definition/import.js +118 -0
  107. package/lib/commands/cuneiform/definition/import.js.map +1 -0
  108. package/lib/commands/cuneiform/definition/list.d.ts +110 -0
  109. package/lib/commands/cuneiform/definition/list.js +351 -0
  110. package/lib/commands/cuneiform/definition/list.js.map +1 -0
  111. package/lib/commands/cuneiform/definition/purge.d.ts +109 -0
  112. package/lib/commands/cuneiform/definition/purge.js +578 -0
  113. package/lib/commands/cuneiform/definition/purge.js.map +1 -0
  114. package/lib/commands/cuneiform/definition/update.d.ts +58 -0
  115. package/lib/commands/cuneiform/definition/update.js +209 -0
  116. package/lib/commands/cuneiform/definition/update.js.map +1 -0
  117. package/lib/commands/cuneiform/mcp/serve.d.ts +56 -0
  118. package/lib/commands/cuneiform/mcp/serve.js +109 -0
  119. package/lib/commands/cuneiform/mcp/serve.js.map +1 -0
  120. package/lib/commands/cuneiform/object/describe.d.ts +61 -0
  121. package/lib/commands/cuneiform/object/describe.js +461 -0
  122. package/lib/commands/cuneiform/object/describe.js.map +1 -0
  123. package/lib/commands/cuneiform/object/list.d.ts +123 -0
  124. package/lib/commands/cuneiform/object/list.js +264 -0
  125. package/lib/commands/cuneiform/object/list.js.map +1 -0
  126. package/lib/commands/cuneiform/org/details.d.ts +99 -0
  127. package/lib/commands/cuneiform/org/details.js +521 -0
  128. package/lib/commands/cuneiform/org/details.js.map +1 -0
  129. package/lib/commands/cuneiform/org/reset.d.ts +46 -0
  130. package/lib/commands/cuneiform/org/reset.js +135 -0
  131. package/lib/commands/cuneiform/org/reset.js.map +1 -0
  132. package/lib/commands/cuneiform/profile/request/cancel.d.ts +59 -0
  133. package/lib/commands/cuneiform/profile/request/cancel.js +202 -0
  134. package/lib/commands/cuneiform/profile/request/cancel.js.map +1 -0
  135. package/lib/commands/cuneiform/profile/request/delete.d.ts +59 -0
  136. package/lib/commands/cuneiform/profile/request/delete.js +223 -0
  137. package/lib/commands/cuneiform/profile/request/delete.js.map +1 -0
  138. package/lib/commands/cuneiform/profile/request/list.d.ts +35 -0
  139. package/lib/commands/cuneiform/profile/request/list.js +102 -0
  140. package/lib/commands/cuneiform/profile/request/list.js.map +1 -0
  141. package/lib/commands/cuneiform/profile.d.ts +93 -0
  142. package/lib/commands/cuneiform/profile.js +353 -0
  143. package/lib/commands/cuneiform/profile.js.map +1 -0
  144. package/lib/commands/cuneiform/summary/purge.d.ts +80 -0
  145. package/lib/commands/cuneiform/summary/purge.js +467 -0
  146. package/lib/commands/cuneiform/summary/purge.js.map +1 -0
  147. package/lib/commands/cuneiform/summary/reprofile.d.ts +60 -0
  148. package/lib/commands/cuneiform/summary/reprofile.js +236 -0
  149. package/lib/commands/cuneiform/summary/reprofile.js.map +1 -0
  150. package/lib/commands/cuneiform/summary/stop.d.ts +59 -0
  151. package/lib/commands/cuneiform/summary/stop.js +234 -0
  152. package/lib/commands/cuneiform/summary/stop.js.map +1 -0
  153. package/lib/commands/cuneiform/user/details.d.ts +77 -0
  154. package/lib/commands/cuneiform/user/details.js +414 -0
  155. package/lib/commands/cuneiform/user/details.js.map +1 -0
  156. package/lib/constants/namespace-constants.d.ts +102 -0
  157. package/lib/constants/namespace-constants.js +225 -0
  158. package/lib/constants/namespace-constants.js.map +1 -0
  159. package/lib/debug/command-debug-proxy.d.ts +101 -0
  160. package/lib/debug/command-debug-proxy.js +171 -0
  161. package/lib/debug/command-debug-proxy.js.map +1 -0
  162. package/lib/debug/debug-logger.d.ts +85 -0
  163. package/lib/debug/debug-logger.js +133 -0
  164. package/lib/debug/debug-logger.js.map +1 -0
  165. package/lib/debug/service-debug-proxy.d.ts +30 -0
  166. package/lib/debug/service-debug-proxy.js +102 -0
  167. package/lib/debug/service-debug-proxy.js.map +1 -0
  168. package/lib/hooks/prerun.d.ts +25 -0
  169. package/lib/hooks/prerun.js +47 -0
  170. package/lib/hooks/prerun.js.map +1 -0
  171. package/lib/mcp/config/mcp-config.d.ts +55 -0
  172. package/lib/mcp/config/mcp-config.js +51 -0
  173. package/lib/mcp/config/mcp-config.js.map +1 -0
  174. package/lib/mcp/config/pagination.d.ts +96 -0
  175. package/lib/mcp/config/pagination.js +108 -0
  176. package/lib/mcp/config/pagination.js.map +1 -0
  177. package/lib/mcp/config/system-prompts.d.ts +18 -0
  178. package/lib/mcp/config/system-prompts.js +92 -0
  179. package/lib/mcp/config/system-prompts.js.map +1 -0
  180. package/lib/mcp/errors.d.ts +23 -0
  181. package/lib/mcp/errors.js +27 -0
  182. package/lib/mcp/errors.js.map +1 -0
  183. package/lib/mcp/schemas/input-schemas.d.ts +327 -0
  184. package/lib/mcp/schemas/input-schemas.js +310 -0
  185. package/lib/mcp/schemas/input-schemas.js.map +1 -0
  186. package/lib/mcp/server.d.ts +40 -0
  187. package/lib/mcp/server.js +316 -0
  188. package/lib/mcp/server.js.map +1 -0
  189. package/lib/mcp/tools/contactpoint-tools.d.ts +14 -0
  190. package/lib/mcp/tools/contactpoint-tools.js +34 -0
  191. package/lib/mcp/tools/contactpoint-tools.js.map +1 -0
  192. package/lib/mcp/tools/definition-io-tools.d.ts +19 -0
  193. package/lib/mcp/tools/definition-io-tools.js +152 -0
  194. package/lib/mcp/tools/definition-io-tools.js.map +1 -0
  195. package/lib/mcp/tools/definition-tools.d.ts +51 -0
  196. package/lib/mcp/tools/definition-tools.js +220 -0
  197. package/lib/mcp/tools/definition-tools.js.map +1 -0
  198. package/lib/mcp/tools/index.d.ts +37 -0
  199. package/lib/mcp/tools/index.js +88 -0
  200. package/lib/mcp/tools/index.js.map +1 -0
  201. package/lib/mcp/tools/object-tools.d.ts +22 -0
  202. package/lib/mcp/tools/object-tools.js +327 -0
  203. package/lib/mcp/tools/object-tools.js.map +1 -0
  204. package/lib/mcp/tools/org-tools.d.ts +14 -0
  205. package/lib/mcp/tools/org-tools.js +177 -0
  206. package/lib/mcp/tools/org-tools.js.map +1 -0
  207. package/lib/mcp/tools/profile-tools.d.ts +59 -0
  208. package/lib/mcp/tools/profile-tools.js +213 -0
  209. package/lib/mcp/tools/profile-tools.js.map +1 -0
  210. package/lib/mcp/tools/summary-tools.d.ts +14 -0
  211. package/lib/mcp/tools/summary-tools.js +38 -0
  212. package/lib/mcp/tools/summary-tools.js.map +1 -0
  213. package/lib/mcp/tools/tool-factory.d.ts +63 -0
  214. package/lib/mcp/tools/tool-factory.js +146 -0
  215. package/lib/mcp/tools/tool-factory.js.map +1 -0
  216. package/lib/mcp/tools/user-tools.d.ts +25 -0
  217. package/lib/mcp/tools/user-tools.js +167 -0
  218. package/lib/mcp/tools/user-tools.js.map +1 -0
  219. package/lib/models/cascade-skip-accumulator.d.ts +25 -0
  220. package/lib/models/cascade-skip-accumulator.js +9 -0
  221. package/lib/models/cascade-skip-accumulator.js.map +1 -0
  222. package/lib/models/date-literal.d.ts +280 -0
  223. package/lib/models/date-literal.js +1164 -0
  224. package/lib/models/date-literal.js.map +1 -0
  225. package/lib/models/object-describe-types.d.ts +173 -0
  226. package/lib/models/object-describe-types.js +9 -0
  227. package/lib/models/object-describe-types.js.map +1 -0
  228. package/lib/models/portability-recipe.d.ts +35 -0
  229. package/lib/models/portability-recipe.js +113 -0
  230. package/lib/models/portability-recipe.js.map +1 -0
  231. package/lib/models/profile-request-types.d.ts +118 -0
  232. package/lib/models/profile-request-types.js +23 -0
  233. package/lib/models/profile-request-types.js.map +1 -0
  234. package/lib/models/profiling-execution-types.d.ts +154 -0
  235. package/lib/models/profiling-execution-types.js +14 -0
  236. package/lib/models/profiling-execution-types.js.map +1 -0
  237. package/lib/models/service-result.d.ts +114 -0
  238. package/lib/models/service-result.js +81 -0
  239. package/lib/models/service-result.js.map +1 -0
  240. package/lib/models/sfdmu-types.d.ts +49 -0
  241. package/lib/models/sfdmu-types.js +23 -0
  242. package/lib/models/sfdmu-types.js.map +1 -0
  243. package/lib/models/status-types.d.ts +38 -0
  244. package/lib/models/status-types.js +12 -0
  245. package/lib/models/status-types.js.map +1 -0
  246. package/lib/models/summary-bulk-types.d.ts +61 -0
  247. package/lib/models/summary-bulk-types.js +23 -0
  248. package/lib/models/summary-bulk-types.js.map +1 -0
  249. package/lib/models/user-details-types.d.ts +188 -0
  250. package/lib/models/user-details-types.js +9 -0
  251. package/lib/models/user-details-types.js.map +1 -0
  252. package/lib/models/year-range.d.ts +78 -0
  253. package/lib/models/year-range.js +153 -0
  254. package/lib/models/year-range.js.map +1 -0
  255. package/lib/operations/CompatibilityCheckOperation.d.ts +62 -0
  256. package/lib/operations/CompatibilityCheckOperation.js +102 -0
  257. package/lib/operations/CompatibilityCheckOperation.js.map +1 -0
  258. package/lib/operations/DefinitionCreateOperation.d.ts +427 -0
  259. package/lib/operations/DefinitionCreateOperation.js +1270 -0
  260. package/lib/operations/DefinitionCreateOperation.js.map +1 -0
  261. package/lib/operations/DefinitionExportOperation.d.ts +155 -0
  262. package/lib/operations/DefinitionExportOperation.js +281 -0
  263. package/lib/operations/DefinitionExportOperation.js.map +1 -0
  264. package/lib/operations/DefinitionImportOperation.d.ts +144 -0
  265. package/lib/operations/DefinitionImportOperation.js +357 -0
  266. package/lib/operations/DefinitionImportOperation.js.map +1 -0
  267. package/lib/operations/DefinitionListOperation.d.ts +66 -0
  268. package/lib/operations/DefinitionListOperation.js +108 -0
  269. package/lib/operations/DefinitionListOperation.js.map +1 -0
  270. package/lib/operations/DefinitionPurgeOperation.d.ts +203 -0
  271. package/lib/operations/DefinitionPurgeOperation.js +465 -0
  272. package/lib/operations/DefinitionPurgeOperation.js.map +1 -0
  273. package/lib/operations/DefinitionUpdateOperation.d.ts +78 -0
  274. package/lib/operations/DefinitionUpdateOperation.js +142 -0
  275. package/lib/operations/DefinitionUpdateOperation.js.map +1 -0
  276. package/lib/operations/OrgDetailsOperation.d.ts +253 -0
  277. package/lib/operations/OrgDetailsOperation.js +456 -0
  278. package/lib/operations/OrgDetailsOperation.js.map +1 -0
  279. package/lib/operations/OrgResetOperation.d.ts +114 -0
  280. package/lib/operations/OrgResetOperation.js +209 -0
  281. package/lib/operations/OrgResetOperation.js.map +1 -0
  282. package/lib/operations/ProfileOperation.d.ts +192 -0
  283. package/lib/operations/ProfileOperation.js +371 -0
  284. package/lib/operations/ProfileOperation.js.map +1 -0
  285. package/lib/operations/ProfileRequestCancelOperation.d.ts +59 -0
  286. package/lib/operations/ProfileRequestCancelOperation.js +137 -0
  287. package/lib/operations/ProfileRequestCancelOperation.js.map +1 -0
  288. package/lib/operations/ProfileRequestDeleteOperation.d.ts +64 -0
  289. package/lib/operations/ProfileRequestDeleteOperation.js +134 -0
  290. package/lib/operations/ProfileRequestDeleteOperation.js.map +1 -0
  291. package/lib/operations/ProfileRequestListOperation.d.ts +39 -0
  292. package/lib/operations/ProfileRequestListOperation.js +61 -0
  293. package/lib/operations/ProfileRequestListOperation.js.map +1 -0
  294. package/lib/operations/SummaryPurgeOperation.d.ts +134 -0
  295. package/lib/operations/SummaryPurgeOperation.js +257 -0
  296. package/lib/operations/SummaryPurgeOperation.js.map +1 -0
  297. package/lib/operations/SummaryReprofileOperation.d.ts +88 -0
  298. package/lib/operations/SummaryReprofileOperation.js +174 -0
  299. package/lib/operations/SummaryReprofileOperation.js.map +1 -0
  300. package/lib/operations/SummaryStopOperation.d.ts +87 -0
  301. package/lib/operations/SummaryStopOperation.js +175 -0
  302. package/lib/operations/SummaryStopOperation.js.map +1 -0
  303. package/lib/services/BulkExecutionService.d.ts +120 -0
  304. package/lib/services/BulkExecutionService.js +535 -0
  305. package/lib/services/BulkExecutionService.js.map +1 -0
  306. package/lib/services/CompatibilityService.d.ts +81 -0
  307. package/lib/services/CompatibilityService.js +118 -0
  308. package/lib/services/CompatibilityService.js.map +1 -0
  309. package/lib/services/ConfigureMode.d.ts +98 -0
  310. package/lib/services/ConfigureMode.js +413 -0
  311. package/lib/services/ConfigureMode.js.map +1 -0
  312. package/lib/services/ContactPointService.d.ts +111 -0
  313. package/lib/services/ContactPointService.js +286 -0
  314. package/lib/services/ContactPointService.js.map +1 -0
  315. package/lib/services/DataAvailabilityService.d.ts +81 -0
  316. package/lib/services/DataAvailabilityService.js +128 -0
  317. package/lib/services/DataAvailabilityService.js.map +1 -0
  318. package/lib/services/DefinitionFieldGenerationService.d.ts +357 -0
  319. package/lib/services/DefinitionFieldGenerationService.js +899 -0
  320. package/lib/services/DefinitionFieldGenerationService.js.map +1 -0
  321. package/lib/services/DefinitionQueryBuilder.d.ts +92 -0
  322. package/lib/services/DefinitionQueryBuilder.js +328 -0
  323. package/lib/services/DefinitionQueryBuilder.js.map +1 -0
  324. package/lib/services/ObjectDescribeService.d.ts +436 -0
  325. package/lib/services/ObjectDescribeService.js +881 -0
  326. package/lib/services/ObjectDescribeService.js.map +1 -0
  327. package/lib/services/ObjectFilteringService.d.ts +484 -0
  328. package/lib/services/ObjectFilteringService.js +1080 -0
  329. package/lib/services/ObjectFilteringService.js.map +1 -0
  330. package/lib/services/ObjectListCommandService.d.ts +467 -0
  331. package/lib/services/ObjectListCommandService.js +904 -0
  332. package/lib/services/ObjectListCommandService.js.map +1 -0
  333. package/lib/services/ObjectListService.d.ts +201 -0
  334. package/lib/services/ObjectListService.js +350 -0
  335. package/lib/services/ObjectListService.js.map +1 -0
  336. package/lib/services/OrgInfoService.d.ts +493 -0
  337. package/lib/services/OrgInfoService.js +1142 -0
  338. package/lib/services/OrgInfoService.js.map +1 -0
  339. package/lib/services/PollingService.d.ts +105 -0
  340. package/lib/services/PollingService.js +117 -0
  341. package/lib/services/PollingService.js.map +1 -0
  342. package/lib/services/ProfileRequestService.d.ts +186 -0
  343. package/lib/services/ProfileRequestService.js +555 -0
  344. package/lib/services/ProfileRequestService.js.map +1 -0
  345. package/lib/services/ProfilingDefinitionService.d.ts +575 -0
  346. package/lib/services/ProfilingDefinitionService.js +1029 -0
  347. package/lib/services/ProfilingDefinitionService.js.map +1 -0
  348. package/lib/services/ProfilingExecutionService.d.ts +122 -0
  349. package/lib/services/ProfilingExecutionService.js +320 -0
  350. package/lib/services/ProfilingExecutionService.js.map +1 -0
  351. package/lib/services/ProfilingSummaryService.d.ts +292 -0
  352. package/lib/services/ProfilingSummaryService.js +688 -0
  353. package/lib/services/ProfilingSummaryService.js.map +1 -0
  354. package/lib/services/RecordTypeService.d.ts +129 -0
  355. package/lib/services/RecordTypeService.js +284 -0
  356. package/lib/services/RecordTypeService.js.map +1 -0
  357. package/lib/services/SFDMUService.d.ts +146 -0
  358. package/lib/services/SFDMUService.js +323 -0
  359. package/lib/services/SFDMUService.js.map +1 -0
  360. package/lib/services/TabDetectionService.d.ts +105 -0
  361. package/lib/services/TabDetectionService.js +206 -0
  362. package/lib/services/TabDetectionService.js.map +1 -0
  363. package/lib/services/UnconfigureMode.d.ts +74 -0
  364. package/lib/services/UnconfigureMode.js +378 -0
  365. package/lib/services/UnconfigureMode.js.map +1 -0
  366. package/lib/services/UserConfigurationService.d.ts +158 -0
  367. package/lib/services/UserConfigurationService.js +574 -0
  368. package/lib/services/UserConfigurationService.js.map +1 -0
  369. package/lib/services/UserConfigurationTypes.d.ts +181 -0
  370. package/lib/services/UserConfigurationTypes.js +14 -0
  371. package/lib/services/UserConfigurationTypes.js.map +1 -0
  372. package/lib/services/UserReadinessService.d.ts +347 -0
  373. package/lib/services/UserReadinessService.js +891 -0
  374. package/lib/services/UserReadinessService.js.map +1 -0
  375. package/lib/services/constants.d.ts +54 -0
  376. package/lib/services/constants.js +71 -0
  377. package/lib/services/constants.js.map +1 -0
  378. package/lib/services/namespace-constants.d.ts +1 -0
  379. package/lib/services/namespace-constants.js +11 -0
  380. package/lib/services/namespace-constants.js.map +1 -0
  381. package/lib/services/namespace-filter.d.ts +36 -0
  382. package/lib/services/namespace-filter.js +109 -0
  383. package/lib/services/namespace-filter.js.map +1 -0
  384. package/lib/services/validation.d.ts +47 -0
  385. package/lib/services/validation.js +119 -0
  386. package/lib/services/validation.js.map +1 -0
  387. package/lib/utils/batch-processor.d.ts +13 -0
  388. package/lib/utils/batch-processor.js +39 -0
  389. package/lib/utils/batch-processor.js.map +1 -0
  390. package/lib/utils/formatting/availability-grid.d.ts +81 -0
  391. package/lib/utils/formatting/availability-grid.js +94 -0
  392. package/lib/utils/formatting/availability-grid.js.map +1 -0
  393. package/lib/utils/formatting/business-process-grid.d.ts +51 -0
  394. package/lib/utils/formatting/business-process-grid.js +58 -0
  395. package/lib/utils/formatting/business-process-grid.js.map +1 -0
  396. package/lib/utils/formatting/command-display.d.ts +154 -0
  397. package/lib/utils/formatting/command-display.js +154 -0
  398. package/lib/utils/formatting/command-display.js.map +1 -0
  399. package/lib/utils/formatting/definition-create-display.d.ts +118 -0
  400. package/lib/utils/formatting/definition-create-display.js +230 -0
  401. package/lib/utils/formatting/definition-create-display.js.map +1 -0
  402. package/lib/utils/formatting/empty-states.d.ts +35 -0
  403. package/lib/utils/formatting/empty-states.js +70 -0
  404. package/lib/utils/formatting/empty-states.js.map +1 -0
  405. package/lib/utils/formatting/errors.d.ts +33 -0
  406. package/lib/utils/formatting/errors.js +72 -0
  407. package/lib/utils/formatting/errors.js.map +1 -0
  408. package/lib/utils/formatting/field-types.d.ts +32 -0
  409. package/lib/utils/formatting/field-types.js +88 -0
  410. package/lib/utils/formatting/field-types.js.map +1 -0
  411. package/lib/utils/formatting/index.d.ts +29 -0
  412. package/lib/utils/formatting/index.js +28 -0
  413. package/lib/utils/formatting/index.js.map +1 -0
  414. package/lib/utils/formatting/indicators.d.ts +113 -0
  415. package/lib/utils/formatting/indicators.js +161 -0
  416. package/lib/utils/formatting/indicators.js.map +1 -0
  417. package/lib/utils/formatting/loading-messages.d.ts +37 -0
  418. package/lib/utils/formatting/loading-messages.js +50 -0
  419. package/lib/utils/formatting/loading-messages.js.map +1 -0
  420. package/lib/utils/formatting/namespace-display.d.ts +31 -0
  421. package/lib/utils/formatting/namespace-display.js +64 -0
  422. package/lib/utils/formatting/namespace-display.js.map +1 -0
  423. package/lib/utils/formatting/numbers.d.ts +73 -0
  424. package/lib/utils/formatting/numbers.js +187 -0
  425. package/lib/utils/formatting/numbers.js.map +1 -0
  426. package/lib/utils/formatting/object-describe-display.d.ts +117 -0
  427. package/lib/utils/formatting/object-describe-display.js +447 -0
  428. package/lib/utils/formatting/object-describe-display.js.map +1 -0
  429. package/lib/utils/formatting/object-list-display.d.ts +225 -0
  430. package/lib/utils/formatting/object-list-display.js +718 -0
  431. package/lib/utils/formatting/object-list-display.js.map +1 -0
  432. package/lib/utils/formatting/org-identity.d.ts +15 -0
  433. package/lib/utils/formatting/org-identity.js +28 -0
  434. package/lib/utils/formatting/org-identity.js.map +1 -0
  435. package/lib/utils/formatting/record-age-grid.d.ts +41 -0
  436. package/lib/utils/formatting/record-age-grid.js +56 -0
  437. package/lib/utils/formatting/record-age-grid.js.map +1 -0
  438. package/lib/utils/formatting/sections.d.ts +108 -0
  439. package/lib/utils/formatting/sections.js +150 -0
  440. package/lib/utils/formatting/sections.js.map +1 -0
  441. package/lib/utils/formatting/tables.d.ts +90 -0
  442. package/lib/utils/formatting/tables.js +113 -0
  443. package/lib/utils/formatting/tables.js.map +1 -0
  444. package/lib/utils/formatting/user-details-display.d.ts +101 -0
  445. package/lib/utils/formatting/user-details-display.js +425 -0
  446. package/lib/utils/formatting/user-details-display.js.map +1 -0
  447. package/lib/utils/pagination/keypress-reader.d.ts +20 -0
  448. package/lib/utils/pagination/keypress-reader.js +63 -0
  449. package/lib/utils/pagination/keypress-reader.js.map +1 -0
  450. package/lib/utils/pagination/paginate-output.d.ts +48 -0
  451. package/lib/utils/pagination/paginate-output.js +136 -0
  452. package/lib/utils/pagination/paginate-output.js.map +1 -0
  453. package/messages/compatibility.check.md +71 -0
  454. package/messages/cuneiform.access.md +138 -0
  455. package/messages/definition.create.md +525 -0
  456. package/messages/definition.export.md +84 -0
  457. package/messages/definition.get.md +147 -0
  458. package/messages/definition.import.md +65 -0
  459. package/messages/definition.list.md +264 -0
  460. package/messages/definition.purge.md +330 -0
  461. package/messages/definition.update.md +118 -0
  462. package/messages/mcp.serve.md +66 -0
  463. package/messages/object.describe.md +205 -0
  464. package/messages/object.list.md +463 -0
  465. package/messages/org.details.md +386 -0
  466. package/messages/org.reset.md +71 -0
  467. package/messages/profile.md +243 -0
  468. package/messages/profile.request.cancel.md +143 -0
  469. package/messages/profile.request.delete.md +139 -0
  470. package/messages/profile.request.list.md +89 -0
  471. package/messages/summary.purge.md +218 -0
  472. package/messages/summary.reprofile.md +150 -0
  473. package/messages/summary.stop.md +157 -0
  474. package/messages/user.details.md +501 -0
  475. package/oclif.lock +3267 -2148
  476. package/oclif.manifest.json +2829 -31
  477. package/package.json +104 -18
  478. package/lib/commands/cuneiform/about.d.ts +0 -13
  479. package/lib/commands/cuneiform/about.js +0 -26
  480. package/lib/commands/cuneiform/about.js.map +0 -1
  481. package/lib/commands/hello/world.d.ts +0 -14
  482. package/lib/commands/hello/world.js +0 -27
  483. package/lib/commands/hello/world.js.map +0 -1
  484. package/lib/index.d.ts +0 -2
  485. package/lib/index.js +0 -2
  486. package/lib/index.js.map +0 -1
  487. package/messages/cuneiform.about.md +0 -19
  488. package/messages/hello.world.md +0 -29
@@ -0,0 +1,1029 @@
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, 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
+ // Phase 1: standard query using the fully-qualified namespace prefix LIKE pattern.
294
+ const phase1 = await this.fetchAllPages(options);
295
+ if (!phase1.success)
296
+ return phase1;
297
+ if (phase1.data.length > 0) {
298
+ this.logger?.log(`Fetched ${phase1.data.length} total definitions across pagination`);
299
+ return createSuccessResult(phase1.data, {
300
+ ...(phase1.warnings ? { warnings: phase1.warnings } : {}),
301
+ message: `Found ${phase1.data.length} definitions`,
302
+ metadata: { duration: Date.now() - startTime },
303
+ });
304
+ }
305
+ // Phase 2 fallback: fires only when Phase 1 returned 0, the requested namespace is
306
+ // 'pnova', and the org itself owns that namespace. In such orgs, objects may be stored
307
+ // without the namespace prefix, so the standard LIKE returns nothing. The wider '%__c'
308
+ // pattern catches them; client-side filtering removes false positives from other packages.
309
+ if (options.namespace?.kind === 'managed' && options.namespace.namespaces.includes('pnova')) {
310
+ const orgNamespace = await this.getOrgNamespace();
311
+ if (orgNamespace === 'pnova') {
312
+ const phase2 = await this.fetchAllPages({ ...options, orgNamespace });
313
+ if (!phase2.success)
314
+ return phase2;
315
+ const namespaces = options.namespace.namespaces;
316
+ const filtered = phase2.data.filter((def) => namespaces.some((ns) => DefinitionQueryBuilder.isObjectInNamespace(def.objectName, ns, orgNamespace)));
317
+ this.logger?.log(`Fetched ${filtered.length} total definitions across pagination`);
318
+ return createSuccessResult(filtered, {
319
+ message: `Found ${filtered.length} definitions`,
320
+ metadata: { duration: Date.now() - startTime },
321
+ });
322
+ }
323
+ }
324
+ this.logger?.log('Fetched 0 total definitions across pagination');
325
+ return createSuccessResult([], {
326
+ message: 'Found 0 definitions',
327
+ metadata: { duration: Date.now() - startTime },
328
+ });
329
+ }
330
+ /**
331
+ * Lists profiling definitions with filtering, pagination, and sorting.
332
+ *
333
+ * Executes two SOQL queries:
334
+ *
335
+ * - An aggregate GROUP BY query over the full filter set (no pagination) that
336
+ * yields totalCount and per-status / per-active bucket counts in one round-trip.
337
+ * - A data query with SELECT, WHERE, ORDER BY, LIMIT, OFFSET for the page.
338
+ *
339
+ * @param options - Filter, pagination, and sort options
340
+ * @returns ServiceResult containing definitions, totalCount, and aggregate summary
341
+ */
342
+ async listDefinitions(options) {
343
+ const startTime = Date.now();
344
+ const emptyResult = {
345
+ definitions: [],
346
+ totalCount: 0,
347
+ summary: { ...EMPTY_LIST_SUMMARY },
348
+ };
349
+ // Validate pagination
350
+ const limit = options.pagination?.limit ?? LIST_DEFAULT_LIMIT;
351
+ const offset = options.pagination?.offset ?? 0;
352
+ const paginationError = validatePagination(limit, offset, MAX_PAGINATION_LIMIT);
353
+ if (paginationError) {
354
+ return createFailureResult(emptyResult, ServiceErrorCodes.INVALID_PAGINATION, paginationError, {
355
+ metadata: { duration: Date.now() - startTime },
356
+ });
357
+ }
358
+ // Validate objects filter if provided
359
+ if (options.filter?.objects !== undefined) {
360
+ for (const name of options.filter.objects) {
361
+ const objectNameError = validateObjectName(name);
362
+ if (objectNameError) {
363
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_OBJECT_NAME, objectNameError, {
364
+ metadata: { duration: Date.now() - startTime },
365
+ });
366
+ }
367
+ }
368
+ }
369
+ // Namespace validation is now performed at the parser boundary
370
+ // (`parseNamespaceFilter` in services/namespace-filter.ts) — the typed
371
+ // NamespaceFilter discriminated union arriving here is already validated.
372
+ try {
373
+ // Build WHERE conditions (shared by both aggregate and data queries)
374
+ const whereBuilder = ProfilingDefinitionService.buildListWhereConditions(options.filter);
375
+ // 1. Aggregate GROUP BY query for totalCount AND summary buckets
376
+ const aggregateBuilder = new CuneiformQueryBuilder()
377
+ .select(['COUNT(Id) cnt', 'pnova__Agg_Status__c', 'pnova__Prop_IsActive__c'])
378
+ .from('pnova__Profiling_Definition__c');
379
+ ProfilingDefinitionService.applyWhereConditions(aggregateBuilder, whereBuilder);
380
+ aggregateBuilder.groupBy(['pnova__Agg_Status__c', 'pnova__Prop_IsActive__c']);
381
+ const aggregateSoql = aggregateBuilder.toSOQL();
382
+ this.logger?.log(`Aggregating profiling definitions: ${aggregateSoql}`);
383
+ const aggregateResult = await this.soqlAdapter.query(aggregateSoql);
384
+ if (!aggregateResult.success) {
385
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, aggregateResult.message ?? 'Profiling definition aggregate query failed', { metadata: { duration: Date.now() - startTime } });
386
+ }
387
+ const { totalCount, summary } = ProfilingDefinitionService.foldAggregateRows(aggregateResult.data.records);
388
+ // 2. Data query with pagination and sort
389
+ const dataBuilder = new CuneiformQueryBuilder()
390
+ .select(DEFINITION_FIELDS.split(', '))
391
+ .from('pnova__Profiling_Definition__c');
392
+ ProfilingDefinitionService.applyWhereConditions(dataBuilder, whereBuilder);
393
+ // Sort
394
+ const sortField = options.sort?.field ?? 'name';
395
+ const sortDirection = (options.sort?.direction ?? 'asc').toUpperCase();
396
+ const soqlSortField = SORT_FIELD_MAP[sortField] ?? 'pnova__Prop_Name__c';
397
+ if (sortField === 'lastProfiledDate') {
398
+ dataBuilder.orderBy(soqlSortField, sortDirection, 'NULLS LAST');
399
+ }
400
+ else {
401
+ dataBuilder.orderBy(soqlSortField, sortDirection);
402
+ }
403
+ dataBuilder.limit(limit);
404
+ dataBuilder.offset(offset);
405
+ const dataSoql = dataBuilder.toSOQL();
406
+ this.logger?.log(`Querying profiling definitions: ${dataSoql}`);
407
+ const queryResult = await this.soqlAdapter.query(dataSoql);
408
+ if (!queryResult.success) {
409
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition query failed', { metadata: { duration: Date.now() - startTime } });
410
+ }
411
+ const definitions = queryResult.data.records.map((record) => ProfilingDefinitionService.mapToProfilingDefinition(record));
412
+ const duration = Date.now() - startTime;
413
+ this.logger?.log(`Listed ${String(definitions.length)} of ${String(totalCount)} profiling definitions`);
414
+ return createSuccessResult({ definitions, totalCount, summary }, {
415
+ message: `Listed ${String(definitions.length)} of ${String(totalCount)} profiling definitions`,
416
+ metadata: { duration },
417
+ });
418
+ }
419
+ catch (error) {
420
+ const errorMessage = error instanceof Error ? error.message : String(error);
421
+ this.logger?.log(`Profiling definition list failed: ${errorMessage}`);
422
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
423
+ metadata: { duration: Date.now() - startTime },
424
+ });
425
+ }
426
+ }
427
+ /**
428
+ * Retrieves a single profiling definition by its Salesforce ID.
429
+ *
430
+ * @param id - The Salesforce record ID (15 or 18 characters)
431
+ * @returns ServiceResult containing the ProfilingDefinition or null if not found
432
+ */
433
+ async getDefinitionById(id) {
434
+ const startTime = Date.now();
435
+ const emptyResult = null;
436
+ // Validate ID format
437
+ const idError = validateSalesforceId(id);
438
+ if (idError) {
439
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_ID, idError, {
440
+ metadata: { duration: Date.now() - startTime },
441
+ });
442
+ }
443
+ try {
444
+ const soql = new CuneiformQueryBuilder()
445
+ .select(DEFINITION_FIELDS.split(', '))
446
+ .from('pnova__Profiling_Definition__c')
447
+ .where('Id', '=', id)
448
+ .limit(1)
449
+ .toSOQL();
450
+ this.logger?.log(`Querying profiling definition by ID: ${id}`);
451
+ const queryResult = await this.soqlAdapter.query(soql);
452
+ if (!queryResult.success) {
453
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition query failed', { metadata: { duration: Date.now() - startTime } });
454
+ }
455
+ const duration = Date.now() - startTime;
456
+ if (queryResult.data.records.length === 0) {
457
+ this.logger?.log(`Profiling definition not found: ${id}`);
458
+ return createSuccessResult(emptyResult, {
459
+ message: `Profiling definition not found: ${id}`,
460
+ warnings: [`No profiling definition found with ID: ${id}`],
461
+ metadata: { duration },
462
+ });
463
+ }
464
+ const definition = ProfilingDefinitionService.mapToProfilingDefinition(queryResult.data.records[0]);
465
+ this.logger?.log(`Found profiling definition: ${definition.name}`);
466
+ return createSuccessResult(definition, {
467
+ message: `Found profiling definition: ${definition.name}`,
468
+ metadata: { duration },
469
+ });
470
+ }
471
+ catch (error) {
472
+ const errorMessage = error instanceof Error ? error.message : String(error);
473
+ this.logger?.log(`Profiling definition query failed: ${errorMessage}`);
474
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
475
+ metadata: { duration: Date.now() - startTime },
476
+ });
477
+ }
478
+ }
479
+ /**
480
+ * Retrieves a single profiling definition by its definition key (e.g., "PD-0001").
481
+ *
482
+ * The key is stored in the standard Name field as an AutoNumber.
483
+ *
484
+ * @param key - The definition key (e.g., "PD-0001")
485
+ * @returns ServiceResult containing the ProfilingDefinition or null if not found
486
+ */
487
+ async getDefinitionByKey(key) {
488
+ const startTime = Date.now();
489
+ const emptyResult = null;
490
+ // Validate key is provided
491
+ const keyError = validateRequiredString(key, 'Definition key');
492
+ if (keyError) {
493
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, keyError, {
494
+ metadata: { duration: Date.now() - startTime },
495
+ });
496
+ }
497
+ try {
498
+ // Name is the standard AutoNumber field (format: PD-{0000})
499
+ const soql = new CuneiformQueryBuilder()
500
+ .select(DEFINITION_FIELDS.split(', '))
501
+ .from('pnova__Profiling_Definition__c')
502
+ .where('Name', '=', key.trim())
503
+ .limit(1)
504
+ .toSOQL();
505
+ this.logger?.log(`Querying profiling definition by key: ${key}`);
506
+ const queryResult = await this.soqlAdapter.query(soql);
507
+ if (!queryResult.success) {
508
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition query failed', { metadata: { duration: Date.now() - startTime } });
509
+ }
510
+ const duration = Date.now() - startTime;
511
+ if (queryResult.data.records.length === 0) {
512
+ this.logger?.log(`Profiling definition not found: ${key}`);
513
+ return createSuccessResult(emptyResult, {
514
+ message: `Profiling definition not found: ${key}`,
515
+ warnings: [`No profiling definition found with key: ${key}`],
516
+ metadata: { duration },
517
+ });
518
+ }
519
+ const definition = ProfilingDefinitionService.mapToProfilingDefinition(queryResult.data.records[0]);
520
+ this.logger?.log(`Found profiling definition: ${definition.name} (key: ${key})`);
521
+ return createSuccessResult(definition, {
522
+ message: `Found profiling definition: ${definition.name}`,
523
+ metadata: { duration },
524
+ });
525
+ }
526
+ catch (error) {
527
+ const errorMessage = error instanceof Error ? error.message : String(error);
528
+ this.logger?.log(`Profiling definition query failed: ${errorMessage}`);
529
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
530
+ metadata: { duration: Date.now() - startTime },
531
+ });
532
+ }
533
+ }
534
+ /**
535
+ * Retrieves multiple profiling definitions by their human-readable keys in a single SOQL query.
536
+ *
537
+ * Replaces the N+1 pattern of calling getDefinitionByKey() per key with a single
538
+ * `WHERE Name IN (...)` query. Returns a Map keyed by the requested key values.
539
+ *
540
+ * @param keys - Array of definition keys (e.g., ['PD-0001', 'PD-0002'])
541
+ * @returns ServiceResult containing a Map of key → ProfilingDefinition (missing keys have null)
542
+ */
543
+ async getDefinitionsByKeys(keys) {
544
+ const startTime = Date.now();
545
+ const emptyResult = new Map();
546
+ if (keys.length === 0) {
547
+ return createSuccessResult(emptyResult, {
548
+ message: 'No keys provided',
549
+ metadata: { duration: Date.now() - startTime },
550
+ });
551
+ }
552
+ try {
553
+ const trimmedKeys = keys.map((k) => k.trim());
554
+ const soql = new CuneiformQueryBuilder()
555
+ .select(DEFINITION_FIELDS.split(', '))
556
+ .from('pnova__Profiling_Definition__c')
557
+ .andWhereIn('Name', trimmedKeys)
558
+ .toSOQL();
559
+ this.logger?.log(`Querying profiling definitions by keys: ${trimmedKeys.join(', ')}`);
560
+ const queryResult = await this.soqlAdapter.query(soql);
561
+ if (!queryResult.success) {
562
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, queryResult.message ?? 'Profiling definition batch query failed', { metadata: { duration: Date.now() - startTime } });
563
+ }
564
+ const duration = Date.now() - startTime;
565
+ // Build result map: key → definition or null
566
+ const resultMap = new Map();
567
+ const recordsByKey = new Map();
568
+ for (const record of queryResult.data.records) {
569
+ recordsByKey.set(record.Name, record);
570
+ }
571
+ for (const key of trimmedKeys) {
572
+ const record = recordsByKey.get(key);
573
+ resultMap.set(key, record ? ProfilingDefinitionService.mapToProfilingDefinition(record) : null);
574
+ }
575
+ const foundCount = queryResult.data.records.length;
576
+ this.logger?.log(`Found ${foundCount}/${trimmedKeys.length} profiling definitions`);
577
+ return createSuccessResult(resultMap, {
578
+ message: `Found ${foundCount} of ${trimmedKeys.length} requested definitions`,
579
+ metadata: { duration },
580
+ });
581
+ }
582
+ catch (error) {
583
+ const errorMessage = error instanceof Error ? error.message : String(error);
584
+ this.logger?.log(`Profiling definition batch query failed: ${errorMessage}`);
585
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_QUERY_FAILED, errorMessage, {
586
+ metadata: { duration: Date.now() - startTime },
587
+ });
588
+ }
589
+ }
590
+ /**
591
+ * Retrieves profiling definitions filtered by type.
592
+ *
593
+ * Convenience method that delegates to getDefinitions() with the type filter.
594
+ *
595
+ * @param type - The definition type to filter by
596
+ * @param options - Additional filter and pagination options
597
+ * @returns ServiceResult containing an array of ProfilingDefinition records
598
+ */
599
+ async getDefinitionsByType(type, options = {}) {
600
+ return this.getDefinitions({ ...options, type });
601
+ }
602
+ /**
603
+ * Retrieves profiling definitions filtered by status.
604
+ *
605
+ * Convenience method that delegates to getDefinitions() with the status filter.
606
+ *
607
+ * @param status - The profiling status to filter by
608
+ * @param options - Additional filter and pagination options
609
+ * @returns ServiceResult containing an array of ProfilingDefinition records
610
+ */
611
+ async getDefinitionsByStatus(status, options = {}) {
612
+ return this.getDefinitions({ ...options, status });
613
+ }
614
+ /**
615
+ * Creates a new profiling definition via the Cuneiform REST API.
616
+ *
617
+ * Definition creation is routed through the REST endpoint which enforces
618
+ * server-side permission checks in GlobalProfilingService.
619
+ *
620
+ * @param input - The definition input containing name, objectName, and optional fields
621
+ * @returns ServiceResult containing the created ProfilingDefinition or null on failure
622
+ */
623
+ async createDefinition(input) {
624
+ const startTime = Date.now();
625
+ const emptyResult = null;
626
+ if (!this.restAdapter) {
627
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'restAdapter is required for create operations.', { metadata: { duration: Date.now() - startTime } });
628
+ }
629
+ return this.createDefinitionViaRest(input, startTime);
630
+ }
631
+ /**
632
+ * Creates multiple profiling definitions via the Cuneiform REST API.
633
+ *
634
+ * Each definition is created individually since the REST endpoint
635
+ * currently supports single creation per request.
636
+ *
637
+ * @param inputs - Array of definition inputs (1-10 items)
638
+ * @returns ServiceResult containing succeeded and failed arrays
639
+ */
640
+ async createDefinitions(inputs) {
641
+ const startTime = Date.now();
642
+ const emptyResult = { succeeded: [], failed: [] };
643
+ if (!this.restAdapter) {
644
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'restAdapter is required for create operations.', { metadata: { duration: Date.now() - startTime } });
645
+ }
646
+ return this.createDefinitionsViaRest(inputs, startTime);
647
+ }
648
+ /**
649
+ * Updates metadata attributes on a profiling definition.
650
+ *
651
+ * Writes only the supplied attributes; untouched columns are preserved.
652
+ * At least one attribute must be provided.
653
+ *
654
+ * @param definitionId - The Salesforce record ID of the definition to update
655
+ * @param attributes - Partial attribute set to write
656
+ * @returns ServiceResult containing the update result
657
+ */
658
+ async updateAttributes(definitionId, attributes) {
659
+ const startTime = Date.now();
660
+ const emptyResult = { id: definitionId, updated: false, updatedAttributes: [] };
661
+ // Validate definition ID
662
+ const idError = validateSalesforceId(definitionId);
663
+ if (idError) {
664
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_ID, idError, {
665
+ metadata: { duration: Date.now() - startTime },
666
+ });
667
+ }
668
+ // Check that REST adapter is configured
669
+ if (!this.restAdapter) {
670
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_UPDATE_FAILED, 'REST adapter required for update operations', { metadata: { duration: Date.now() - startTime } });
671
+ }
672
+ // Build the partial update payload — only supplied attributes
673
+ // eslint-disable-next-line camelcase -- Salesforce custom field API names require this casing
674
+ const payload = {};
675
+ const updatedAttributes = [];
676
+ if (attributes.name !== undefined) {
677
+ // eslint-disable-next-line camelcase -- Salesforce custom field API name
678
+ payload.pnova__Prop_Name__c = attributes.name;
679
+ updatedAttributes.push('name');
680
+ }
681
+ if (attributes.category !== undefined) {
682
+ // eslint-disable-next-line camelcase -- Salesforce custom field API name
683
+ payload.pnova__Prop_Category__c = attributes.category;
684
+ updatedAttributes.push('category');
685
+ }
686
+ if (attributes.timeCategory !== undefined) {
687
+ // eslint-disable-next-line camelcase -- Salesforce custom field API name
688
+ payload.pnova__Prop_TimeCategory__c = attributes.timeCategory;
689
+ updatedAttributes.push('timeCategory');
690
+ }
691
+ if (attributes.segmentCategory !== undefined) {
692
+ // eslint-disable-next-line camelcase -- Salesforce custom field API name
693
+ payload.pnova__Prop_SegmentCategory__c = attributes.segmentCategory;
694
+ updatedAttributes.push('segmentCategory');
695
+ }
696
+ if (attributes.description !== undefined) {
697
+ // eslint-disable-next-line camelcase -- Salesforce custom field API name
698
+ payload.pnova__Prop_Description__c = attributes.description;
699
+ updatedAttributes.push('description');
700
+ }
701
+ try {
702
+ this.logger?.log(`Updating definition ${definitionId}: ${updatedAttributes.join(', ')}`);
703
+ const updateResult = await this.restAdapter.updateRecord('pnova__Profiling_Definition__c', definitionId, payload);
704
+ const duration = Date.now() - startTime;
705
+ if (!updateResult.success) {
706
+ this.logger?.log(`Definition attribute update failed: ${updateResult.message ?? 'Unknown error'}`);
707
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_UPDATE_FAILED, updateResult.message ?? 'Definition attribute update failed', { metadata: { duration } });
708
+ }
709
+ this.logger?.log(`Definition ${definitionId} attributes updated successfully`);
710
+ return createSuccessResult({ id: definitionId, updated: true, updatedAttributes }, {
711
+ message: `Updated definition attributes: ${updatedAttributes.join(', ')}`,
712
+ metadata: { duration },
713
+ });
714
+ }
715
+ catch (error) {
716
+ const errorMessage = error instanceof Error ? error.message : String(error);
717
+ this.logger?.log(`Definition attribute update failed: ${errorMessage}`);
718
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_UPDATE_FAILED, errorMessage, {
719
+ metadata: { duration: Date.now() - startTime },
720
+ });
721
+ }
722
+ }
723
+ /**
724
+ * Deletes profiling definitions by their Salesforce IDs.
725
+ *
726
+ * Safety checks are applied before deletion:
727
+ * - Definition must exist
728
+ * - Definition must have no associated summaries (hasRelatedSummaries field)
729
+ *
730
+ * Definitions can be deleted regardless of profiling status when no
731
+ * associated summaries exist.
732
+ *
733
+ * Definitions that fail safety checks are skipped with reasons provided.
734
+ *
735
+ * @param ids - Array of Salesforce record IDs to delete (1-200 items)
736
+ * @param options - Optional progress callback and configuration
737
+ * @returns ServiceResult containing deletion counts and skip/failure details
738
+ */
739
+ async deleteDefinitions(ids, options) {
740
+ const startTime = Date.now();
741
+ const emptyResult = {
742
+ deleted: 0,
743
+ skipped: 0,
744
+ failed: 0,
745
+ skipReasons: [],
746
+ failures: [],
747
+ };
748
+ // Validate ids array is not empty
749
+ if (ids.length === 0) {
750
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_DELETE_FAILED, 'Definition IDs array cannot be empty', { metadata: { duration: Date.now() - startTime } });
751
+ }
752
+ // Validate REST adapter is available
753
+ if (!this.restAdapter) {
754
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_DELETE_FAILED, 'REST adapter required for delete operations', { metadata: { duration: Date.now() - startTime } });
755
+ }
756
+ // Validate all IDs have valid format
757
+ for (const id of ids) {
758
+ const idError = validateSalesforceId(id);
759
+ if (idError) {
760
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_ID, `Invalid ID "${id}": ${idError}`, {
761
+ metadata: { duration: Date.now() - startTime },
762
+ });
763
+ }
764
+ }
765
+ const result = {
766
+ deleted: 0,
767
+ skipped: 0,
768
+ failed: 0,
769
+ skipReasons: [],
770
+ failures: [],
771
+ };
772
+ const total = ids.length;
773
+ let current = 0;
774
+ // Process each ID sequentially - intentional for safe deletion with proper error handling
775
+ // Each operation depends on the previous (safety checks before delete)
776
+ // eslint-disable-next-line no-await-in-loop -- Sequential processing for safe deletion with individual error handling
777
+ for (const id of ids) {
778
+ current++;
779
+ try {
780
+ // Look up the definition
781
+ // eslint-disable-next-line no-await-in-loop -- Sequential: must verify existence before deletion
782
+ const lookupResult = await this.getDefinitionById(id);
783
+ if (!lookupResult.success) {
784
+ result.failed++;
785
+ result.failures.push({
786
+ id,
787
+ error: lookupResult.message ?? 'Failed to lookup definition',
788
+ });
789
+ options?.onProgress?.({ id, name: id, status: 'failed', reason: 'lookup_failed', current, total });
790
+ continue;
791
+ }
792
+ // Check if definition exists
793
+ if (lookupResult.data === null) {
794
+ result.skipped++;
795
+ result.skipReasons.push({
796
+ id,
797
+ reason: 'not_found',
798
+ });
799
+ options?.onProgress?.({ id, name: id, status: 'skipped', reason: 'not_found', current, total });
800
+ continue;
801
+ }
802
+ const definition = lookupResult.data;
803
+ const defMeta = {
804
+ key: definition.key,
805
+ objectName: definition.objectName,
806
+ objectLabel: definition.objectLabel,
807
+ category: definition.category,
808
+ timeCategory: definition.timeCategory,
809
+ segmentCategory: definition.segmentCategory,
810
+ profilingStatus: definition.status,
811
+ };
812
+ // Safety check: Check for associated summaries
813
+ // Use hasRelatedSummaries field (formula field on the definition object)
814
+ const hasSummaries = definition.hasRelatedSummaries === true;
815
+ if (hasSummaries) {
816
+ result.skipped++;
817
+ result.skipReasons.push({
818
+ id,
819
+ name: definition.name,
820
+ reason: 'has_summaries',
821
+ });
822
+ options?.onProgress?.({
823
+ id,
824
+ ...defMeta,
825
+ name: definition.name,
826
+ status: 'skipped',
827
+ reason: 'has_summaries',
828
+ current,
829
+ total,
830
+ });
831
+ continue;
832
+ }
833
+ // All safety checks passed - delete the definition
834
+ // eslint-disable-next-line no-await-in-loop -- Sequential: dependent on prior safety checks passing
835
+ const deleteResult = await this.restAdapter.deleteRecord('pnova__Profiling_Definition__c', id);
836
+ if (!deleteResult.success) {
837
+ const deleteError = deleteResult.message ?? 'Failed to delete definition';
838
+ result.failed++;
839
+ result.failures.push({
840
+ id,
841
+ name: definition.name,
842
+ error: deleteError,
843
+ });
844
+ options?.onProgress?.({
845
+ id,
846
+ ...defMeta,
847
+ name: definition.name,
848
+ status: 'failed',
849
+ reason: deleteError,
850
+ current,
851
+ total,
852
+ });
853
+ continue;
854
+ }
855
+ result.deleted++;
856
+ this.logger?.log(`Deleted profiling definition: ${id}`);
857
+ options?.onProgress?.({ id, ...defMeta, name: definition.name, status: 'deleted', current, total });
858
+ }
859
+ catch (error) {
860
+ const errorMessage = error instanceof Error ? error.message : String(error);
861
+ result.failed++;
862
+ result.failures.push({
863
+ id,
864
+ error: errorMessage,
865
+ });
866
+ options?.onProgress?.({ id, name: id, status: 'failed', reason: errorMessage, current, total });
867
+ }
868
+ }
869
+ const duration = Date.now() - startTime;
870
+ const totalProcessed = result.deleted + result.skipped + result.failed;
871
+ const summaryMessage = `Deleted ${result.deleted}/${totalProcessed} definitions (${result.skipped} skipped, ${result.failed} failed)`;
872
+ this.logger?.log(summaryMessage);
873
+ return createSuccessResult(result, {
874
+ message: summaryMessage,
875
+ warnings: result.skipped > 0 || result.failed > 0 ? [`${result.skipped} skipped, ${result.failed} failed`] : undefined,
876
+ metadata: { duration },
877
+ });
878
+ }
879
+ /**
880
+ * Paginates through all definition pages for the given options.
881
+ * Returns partial success with warnings if pagination fails mid-stream after
882
+ * collecting at least one page; returns failure if the first page fails.
883
+ */
884
+ async fetchAllPages(options) {
885
+ const allDefinitions = [];
886
+ let offset = 0;
887
+ const pageSize = MAX_PAGINATION_LIMIT;
888
+ // eslint-disable-next-line no-constant-condition -- Pagination loop exits on short page or failure
889
+ while (true) {
890
+ // eslint-disable-next-line no-await-in-loop -- Sequential pagination: each page depends on knowing if more exist
891
+ const pageResult = await this.getDefinitions({ ...options, limit: pageSize, offset });
892
+ if (!pageResult.success) {
893
+ if (allDefinitions.length > 0) {
894
+ this.logger?.log(`Pagination failed at offset ${offset}, using ${allDefinitions.length} definitions fetched so far`);
895
+ return createSuccessResult(allDefinitions, {
896
+ warnings: [`Pagination incomplete: failed at offset ${offset}. Results may be partial.`],
897
+ });
898
+ }
899
+ return pageResult;
900
+ }
901
+ allDefinitions.push(...pageResult.data);
902
+ if (pageResult.data.length < pageSize) {
903
+ break;
904
+ }
905
+ offset += pageSize;
906
+ }
907
+ return createSuccessResult(allDefinitions);
908
+ }
909
+ /**
910
+ * Resolves the org's own NamespacePrefix via a single SOQL query.
911
+ * Returns undefined if the org has no namespace or if the query fails.
912
+ */
913
+ async getOrgNamespace() {
914
+ try {
915
+ const result = await this.soqlAdapter.query('SELECT NamespacePrefix FROM Organization LIMIT 1');
916
+ if (result.success && result.data.records.length > 0) {
917
+ return result.data.records[0].NamespacePrefix ?? undefined;
918
+ }
919
+ }
920
+ catch {
921
+ // Silently fall through — callers use the standard LIKE filter only
922
+ }
923
+ return undefined;
924
+ }
925
+ // NOTE: createDefinitionViaApex and createDefinitionsViaApex removed during REST API migration (CLI-1150).
926
+ // These methods used anonymous Apex routing via GlobalProfilingService and have been replaced
927
+ // by createDefinitionViaRest and createDefinitionsViaRest.
928
+ /**
929
+ * Creates a single definition via the Cuneiform REST API.
930
+ */
931
+ async createDefinitionViaRest(input, startTime) {
932
+ const emptyResult = null;
933
+ // Validate objectName
934
+ const objectNameError = validateObjectName(input.objectName);
935
+ if (objectNameError) {
936
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_INVALID_OBJECT_NAME, objectNameError, {
937
+ metadata: { duration: Date.now() - startTime },
938
+ });
939
+ }
940
+ try {
941
+ this.logger?.log(`Creating profiling definition for object: ${input.objectName}`);
942
+ const requestBody = ProfilingDefinitionService.buildCreateDefinitionRequestBody(input);
943
+ const restResult = await this.restAdapter.request({
944
+ url: `${PROFILING_DEFINITION_REST_BASE}/create-definition`,
945
+ method: 'POST',
946
+ body: requestBody,
947
+ });
948
+ if (!restResult.success) {
949
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, restResult.message ?? 'REST API call failed', { metadata: { duration: Date.now() - startTime } });
950
+ }
951
+ const response = restResult.data;
952
+ if (!response.success) {
953
+ const errorMsg = response.errors && response.errors.length > 0 ? response.errors.join('; ') : 'Definition creation failed';
954
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, errorMsg, {
955
+ metadata: { duration: Date.now() - startTime },
956
+ });
957
+ }
958
+ if (!response.results || response.results.length === 0) {
959
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'No results returned from profiling definition REST API', { metadata: { duration: Date.now() - startTime } });
960
+ }
961
+ const createdId = response.results[0].id;
962
+ this.logger?.log(`Created profiling definition with ID: ${createdId}`);
963
+ // Query back the full definition record
964
+ const queryResult = await this.getDefinitionById(createdId);
965
+ if (!queryResult.success || queryResult.data === null) {
966
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, queryResult.message ?? 'Failed to retrieve created definition', { metadata: { duration: Date.now() - startTime } });
967
+ }
968
+ const duration = Date.now() - startTime;
969
+ this.logger?.log(`Created profiling definition: ${queryResult.data.name} (${queryResult.data.key})`);
970
+ return createSuccessResult(queryResult.data, {
971
+ message: `Created profiling definition: ${queryResult.data.name}`,
972
+ metadata: { duration },
973
+ });
974
+ }
975
+ catch (error) {
976
+ const errorMessage = error instanceof Error ? error.message : String(error);
977
+ this.logger?.log(`Failed to create profiling definition: ${errorMessage}`);
978
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, errorMessage, {
979
+ metadata: { duration: Date.now() - startTime },
980
+ });
981
+ }
982
+ }
983
+ /**
984
+ * Creates multiple definitions via the Cuneiform REST API.
985
+ *
986
+ * The REST endpoint supports single creation, so definitions are created sequentially.
987
+ */
988
+ async createDefinitionsViaRest(inputs, startTime) {
989
+ const emptyResult = { succeeded: [], failed: [] };
990
+ if (inputs.length === 0) {
991
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, 'Inputs array must contain at least one definition.', { metadata: { duration: Date.now() - startTime } });
992
+ }
993
+ try {
994
+ this.logger?.log(`Creating ${inputs.length} profiling definitions via REST API`);
995
+ const succeeded = [];
996
+ const failed = [];
997
+ /* eslint-disable no-await-in-loop -- Sequential creation to avoid overwhelming the org */
998
+ for (const input of inputs) {
999
+ const result = await this.createDefinitionViaRest(input, Date.now());
1000
+ if (result.success && result.data) {
1001
+ succeeded.push(result.data);
1002
+ }
1003
+ else {
1004
+ failed.push({
1005
+ input,
1006
+ error: result.message ?? 'Creation failed',
1007
+ errorCode: result.errorCode ?? ServiceErrorCodes.DEFINITION_CREATE_FAILED,
1008
+ });
1009
+ }
1010
+ }
1011
+ /* eslint-enable no-await-in-loop */
1012
+ const duration = Date.now() - startTime;
1013
+ this.logger?.log(`Created ${succeeded.length}/${inputs.length} definitions (${failed.length} failed)`);
1014
+ return createSuccessResult({ succeeded, failed }, {
1015
+ message: `Created ${succeeded.length}/${inputs.length} definitions`,
1016
+ warnings: failed.length > 0 ? [`${failed.length} definition(s) failed to create`] : undefined,
1017
+ metadata: { duration },
1018
+ });
1019
+ }
1020
+ catch (error) {
1021
+ const errorMessage = error instanceof Error ? error.message : String(error);
1022
+ this.logger?.log(`Bulk create operation failed: ${errorMessage}`);
1023
+ return createFailureResult(emptyResult, ServiceErrorCodes.DEFINITION_CREATE_FAILED, errorMessage, {
1024
+ metadata: { duration: Date.now() - startTime },
1025
+ });
1026
+ }
1027
+ }
1028
+ }
1029
+ //# sourceMappingURL=ProfilingDefinitionService.js.map