@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,1121 @@
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 { MAX_PAGINATION_LIMIT } from '../services/constants.js';
10
+ import { DefinitionFieldGenerationService } from '../services/DefinitionFieldGenerationService.js';
11
+ /**
12
+ * Error codes specific to create operations.
13
+ */
14
+ export const CreateErrorCodes = {
15
+ /** Object filtering failed */
16
+ FILTER_FAILED: 'CREATE_FILTER_FAILED',
17
+ /** No objects found matching filters */
18
+ NO_OBJECTS_FOUND: 'CREATE_NO_OBJECTS_FOUND',
19
+ /** None of the specified --objects exist in the org */
20
+ OBJECTS_NOT_FOUND: 'CREATE_OBJECTS_NOT_FOUND',
21
+ /** All objects already have definitions */
22
+ ALL_OBJECTS_SKIPPED: 'CREATE_ALL_OBJECTS_SKIPPED',
23
+ /** Operation failed unexpectedly */
24
+ OPERATION_FAILED: 'CREATE_OPERATION_FAILED',
25
+ /** No objects have been profiled yet */
26
+ NO_PROFILED_OBJECTS: 'CREATE_NO_PROFILED_OBJECTS',
27
+ };
28
+ /**
29
+ * Orchestrates bulk creation of profiling definitions for filtered objects.
30
+ *
31
+ * Follows the 4-layer architecture: Command -> Operation -> Service -> API
32
+ * This operation layer handles business logic orchestration:
33
+ * 1. Filters objects using ObjectFilteringService
34
+ * 2. Checks for existing definitions using ProfilingDefinitionService
35
+ * 3. Creates definitions for new objects only (deduplication)
36
+ * 4. Reports created/failed/skipped statistics
37
+ *
38
+ * Pure field generation logic (naming, categorisation, description, candidate inputs)
39
+ * is delegated to DefinitionFieldGenerationService.
40
+ */
41
+ export class DefinitionCreateOperation {
42
+ definitionService;
43
+ filteringService;
44
+ logger;
45
+ profilingSummaryService;
46
+ recordTypeService;
47
+ dataAvailabilityService;
48
+ restClient;
49
+ /** Exposes the date literal constant map for external consumers and tests. */
50
+ static DATE_LITERAL_MAP = DefinitionFieldGenerationService.DATE_LITERAL_MAP;
51
+ /** The bullet separator used in definition names. */
52
+ static NAME_SEPARATOR = DefinitionFieldGenerationService.NAME_SEPARATOR;
53
+ /**
54
+ * Creates a new DefinitionCreateOperation instance.
55
+ *
56
+ * @param definitionService - Service for creating and querying profiling definitions
57
+ * @param filteringService - Service for filtering Salesforce objects
58
+ * @param logger - Optional logger for debug output
59
+ * @param profilingSummaryService - Optional service for querying profiled objects (required when profiled=true)
60
+ * @param recordTypeService - Optional service for querying record types (required when method=recordtype)
61
+ */
62
+ constructor(definitionService, filteringService, logger, profilingSummaryService, recordTypeService, dataAvailabilityService, restClient) {
63
+ this.definitionService = definitionService;
64
+ this.filteringService = filteringService;
65
+ this.logger = logger;
66
+ this.profilingSummaryService = profilingSummaryService;
67
+ this.recordTypeService = recordTypeService;
68
+ this.dataAvailabilityService = dataAvailabilityService;
69
+ this.restClient = restClient;
70
+ }
71
+ // ── Public Static Methods ────────────────────────────────────────────
72
+ /**
73
+ * Resolves the definition name from the method and context.
74
+ * Single source of truth for definition naming across all definition types.
75
+ *
76
+ * @param label - Object label (e.g., 'Account', 'Lead')
77
+ * @param method - ISV method (metadata, historical, comparative)
78
+ * @param context - Optional context: timeLabel, year, recordTypeName, outcomeLabels, unbounded
79
+ * @returns The formatted definition name
80
+ */
81
+ static resolveDefinitionName(...args) {
82
+ return DefinitionFieldGenerationService.resolveDefinitionName(...args);
83
+ }
84
+ /**
85
+ * Resolves all definition metadata (category, timeCategory, segmentCategory, description)
86
+ * from the method and context. Single source of truth for definition classification.
87
+ */
88
+ static resolveDefinitionMetadata(...args) {
89
+ return DefinitionFieldGenerationService.resolveDefinitionMetadata(...args);
90
+ }
91
+ /**
92
+ * Formats a human-readable message for a per-object result.
93
+ */
94
+ static formatObjectMessage(result) {
95
+ switch (result.status) {
96
+ case 'success':
97
+ return `created "${result.definitionName}"`;
98
+ case 'skip':
99
+ return 'definition already exists';
100
+ case 'fail':
101
+ return result.error ?? 'unknown error';
102
+ case 'preview':
103
+ return `would create "${result.definitionName}"`;
104
+ }
105
+ }
106
+ /**
107
+ * Derives the time category display value from an input's method and year.
108
+ */
109
+ static resolveTimeCategory(input) {
110
+ if (!input)
111
+ return undefined;
112
+ if (input.timeCategory)
113
+ return input.timeCategory;
114
+ if (input.method === 'metadata')
115
+ return 'N/A';
116
+ if (input.comparativeYear !== undefined) {
117
+ return input.usePrior
118
+ ? `${input.comparativeYear} vs Prior`
119
+ : `${input.comparativeYear} vs ${input.comparativeYear - 1}`;
120
+ }
121
+ if (input.historicalYear !== undefined) {
122
+ return String(input.historicalYear);
123
+ }
124
+ return 'Lifetime';
125
+ }
126
+ /**
127
+ * Derives the segment category display value from an input. Prefers the
128
+ * pre-resolved `input.segmentCategory` (populated by the field generation
129
+ * service, which honors the --segment-category override and falls back to
130
+ * method-derived defaults like 'N/A', 'Historical', or record type name).
131
+ * Falls back to `input.recordTypeName` for back-compat with consumers that
132
+ * build inputs without going through `resolveDefinitionMetadata`.
133
+ */
134
+ static resolveSegmentCategory(input) {
135
+ if (!input)
136
+ return undefined;
137
+ return input.segmentCategory ?? input.recordTypeName;
138
+ }
139
+ /**
140
+ * Maps Salesforce objects to their outcome boolean fields.
141
+ *
142
+ * @param objectName - Salesforce object API name (e.g., 'Opportunity', 'Case', 'Lead')
143
+ * @returns Outcome field mapping, or undefined if the object has no outcome field
144
+ */
145
+ static getOutcomeField(objectName) {
146
+ return DefinitionFieldGenerationService.getOutcomeField(objectName);
147
+ }
148
+ /**
149
+ * Builds a single outcome definition input for a given object, outcome mapping, and optional time/RT context.
150
+ * Consolidates the repeated context + input construction pattern used across buildOutcomeCandidateInputs
151
+ * and buildInputsForRecordType.
152
+ */
153
+ static buildOutcomeInput(...args) {
154
+ return DefinitionFieldGenerationService.buildOutcomeInput(...args);
155
+ }
156
+ /**
157
+ * Builds an ISV-compatible filterJson string for business process outcome comparisons.
158
+ * SetA filters for the true outcome, SetB filters for the false outcome.
159
+ * Produces the expression builder JSON schema that `fsc_expressionBuilder3` expects.
160
+ *
161
+ * @param fieldName - Boolean field API name (e.g., 'IsWon', 'IsClosed', 'IsConverted')
162
+ * @param objectName - Salesforce object API name (e.g., 'Opportunity', 'Case', 'Lead')
163
+ * @returns JSON string compatible with GlobalProfilingService.createProfilingDefinition()
164
+ */
165
+ static buildOutcomeFilterJson(...args) {
166
+ return DefinitionFieldGenerationService.buildOutcomeFilterJson(...args);
167
+ }
168
+ // ── Private Static Helpers (execution) ────────────────────────────
169
+ /**
170
+ * Applies outcome pre-filtering for the REST path. For outcome method, only objects
171
+ * with outcome fields (Opportunity, Case, Lead) are eligible. Returns a failure result
172
+ * when no eligible objects remain; otherwise returns the filtered array.
173
+ */
174
+ /**
175
+ * Composes the `nameSuffix` value sent to the ISV `create-smart` REST endpoint, layering the
176
+ * `No Value Frequency` disambiguator ahead of any user-supplied `--name-suffix`. The bullet
177
+ * separator prefix (`• `) is required because the server joins suffix segments with a
178
+ * plain space — this CLI carries the bullet so the final rendered name reads consistently
179
+ * with locally-built names from `DefinitionFieldGenerationService.buildName`.
180
+ *
181
+ * CLI-3064: Without the disambiguator, value-frequency and no-value-frequency variants of
182
+ * the same (object, method, time-segment) resolve to identical names on both client and
183
+ * server; the second invocation is silently dropped by the name-keyed dedup gate. Layering
184
+ * the disambiguator ahead of the user suffix preserves the user's `--name-suffix` semantics
185
+ * while disambiguating the variant.
186
+ *
187
+ * @param userSuffix - User-supplied `--name-suffix` value (optional)
188
+ * @param noValueFrequency - True when the request originates from `--no-value-frequency`
189
+ * @returns Composed suffix to send as `SmartCreateRequest.options.nameSuffix`, or undefined when neither applies
190
+ */
191
+ static composeRestNameSuffix(userSuffix, noValueFrequency) {
192
+ const SEP = '• ';
193
+ const variant = noValueFrequency ? 'No Value Frequency' : undefined;
194
+ if (variant && userSuffix)
195
+ return `${SEP}${variant} ${SEP}${userSuffix}`;
196
+ if (variant)
197
+ return `${SEP}${variant}`;
198
+ if (userSuffix)
199
+ return `${SEP}${userSuffix}`;
200
+ return undefined;
201
+ }
202
+ static applyOutcomeFilter(objects, method, emptyResult, startTime) {
203
+ if (method !== 'outcome')
204
+ return objects;
205
+ const eligible = objects.filter((o) => DefinitionCreateOperation.getOutcomeField(o.name) !== undefined);
206
+ if (eligible.length === 0) {
207
+ return createFailureResult(emptyResult, CreateErrorCodes.NO_OBJECTS_FOUND, 'No objects with outcome fields found. Outcome definitions support Opportunity (Won vs Lost), Case (Closed vs Open), and Lead (Converted vs Unconverted) only.', { metadata: { duration: Date.now() - startTime } });
208
+ }
209
+ return eligible;
210
+ }
211
+ /**
212
+ * Invokes the onPreviewReady callback if provided and not in dry-run mode.
213
+ * Returns a cancellation result if the user declines, or undefined to proceed.
214
+ */
215
+ static async invokePreviewCallback(options, createInputs, skippedInputs, totalCount, skippedCount, recordCounts, emptyResult, startTime) {
216
+ if (!options.onPreviewReady || options.dryRun)
217
+ return undefined;
218
+ try {
219
+ const proceed = await options.onPreviewReady({
220
+ toCreate: createInputs,
221
+ toSkip: skippedInputs,
222
+ total: totalCount,
223
+ recordCounts,
224
+ });
225
+ if (!proceed) {
226
+ return createSuccessResult({ ...emptyResult, cancelled: true, skipped: skippedCount, total: totalCount }, { message: 'Creation cancelled by user.', metadata: { duration: Date.now() - startTime } });
227
+ }
228
+ return undefined;
229
+ }
230
+ catch (err) {
231
+ return createFailureResult(emptyResult, CreateErrorCodes.OPERATION_FAILED, `Confirmation prompt failed: ${err instanceof Error ? err.message : String(err)}`);
232
+ }
233
+ }
234
+ /**
235
+ * Maps a server-side SmartCreateDefinitionResult to an ObjectResult.
236
+ */
237
+ static mapServerResult(sr) {
238
+ return {
239
+ objectName: sr.objectName,
240
+ objectLabel: sr.objectName,
241
+ status: sr.status === 'created'
242
+ ? 'success'
243
+ : sr.status === 'skipped'
244
+ ? 'skip'
245
+ : sr.status === 'preview'
246
+ ? 'preview'
247
+ : 'fail',
248
+ definitionName: sr.definitionName,
249
+ definitionId: sr.definitionId,
250
+ definitionKey: sr.definitionKey,
251
+ fieldCount: sr.fieldCount,
252
+ type: sr.type,
253
+ category: sr.category,
254
+ timeCategory: sr.timeCategory,
255
+ segmentCategory: sr.segmentCategory,
256
+ };
257
+ }
258
+ /** Derives the definition type for a dry-run preview result from the requested method. */
259
+ static derivePreviewType(method) {
260
+ if (method === 'metadata')
261
+ return 'metadata';
262
+ if (method === 'historical')
263
+ return 'historical';
264
+ return 'comparative';
265
+ }
266
+ /** Derives the definition category for a dry-run preview result from the requested method. */
267
+ static derivePreviewCategory(method) {
268
+ if (method === 'metadata')
269
+ return 'Metadata';
270
+ if (method === 'recordtype')
271
+ return 'Record Types';
272
+ if (method === 'outcome')
273
+ return 'Comparative';
274
+ return 'Baseline';
275
+ }
276
+ /**
277
+ * Normalizes a REST-path result for dry-run uniformity (CLI-1832).
278
+ *
279
+ * When options.dryRun is true and the server returned status='skipped' (because the
280
+ * definition already exists), the JSON result's per-item status is remapped to 'preview'
281
+ * so callers see uniform dry-run output across create and skip paths. This mirrors the
282
+ * local-path buildDryRunResult behavior (see :936-937). Progress callbacks still fire
283
+ * with status='skip' so human UX differentiates "already exists" from "would create".
284
+ *
285
+ * After normalization, type/category are back-filled from the method when undefined
286
+ * (ISV create-smart omits classification fields per CLI-1756). 'full' is excluded
287
+ * because it produces multiple definition types per object.
288
+ */
289
+ static normalizeDryRunResult(r, sr, isDryRun, method) {
290
+ if (isDryRun && sr.status === 'skipped') {
291
+ // eslint-disable-next-line no-param-reassign -- normalizing result status in-place for uniform dry-run output (CLI-1832)
292
+ r.status = 'preview';
293
+ }
294
+ if (r.status === 'preview' && r.type === undefined && method !== 'full') {
295
+ // eslint-disable-next-line no-param-reassign -- back-filling classification in-place (CLI-1756: ISV omits these)
296
+ r.type = DefinitionCreateOperation.derivePreviewType(method);
297
+ // eslint-disable-next-line no-param-reassign -- back-filling classification in-place (CLI-1756)
298
+ r.category = DefinitionCreateOperation.derivePreviewCategory(method);
299
+ }
300
+ }
301
+ /** Fires the onObjectComplete progress callback for a single processed result. */
302
+ static notifyObjectComplete(r, sr, current, total, options) {
303
+ // CLI-1832: dry-run normalizes server 'skipped' → r.status='preview' for uniform JSON
304
+ // output. The progress callback still surfaces 'skip' from the original server status
305
+ // so human UX differentiates "already exists" from "would create". This mirrors
306
+ // buildDryRunResult's local-path behavior (see :936-937 and :945).
307
+ const callbackStatus = sr.status === 'skipped' ? 'skip' : r.status === 'preview' ? 'preview' : r.status;
308
+ const callbackMessage = sr.status === 'skipped'
309
+ ? 'definition already exists'
310
+ : r.status === 'success'
311
+ ? `created "${r.definitionName}"`
312
+ : r.status === 'skip'
313
+ ? 'definition already exists'
314
+ : r.error ?? sr.errorMessage ?? 'unknown';
315
+ options.onObjectComplete?.({
316
+ objectName: r.objectName,
317
+ status: callbackStatus,
318
+ message: callbackMessage,
319
+ current,
320
+ total,
321
+ type: r.type,
322
+ definitionName: r.definitionName,
323
+ definitionKey: r.definitionKey,
324
+ recordTypeName: r.segmentCategory,
325
+ category: r.category,
326
+ timeCategory: r.timeCategory,
327
+ segmentCategory: r.segmentCategory,
328
+ fieldCount: r.fieldCount,
329
+ });
330
+ }
331
+ // ── Public Instance Methods ──────────────────────────────────────────
332
+ /**
333
+ * Executes the definition create operation.
334
+ *
335
+ * @param options - Create operation options
336
+ * @returns ServiceResult containing creation statistics
337
+ */
338
+ // eslint-disable-next-line complexity -- 7-step orchestration pipeline with error handling at each step
339
+ async execute(options) {
340
+ const startTime = Date.now();
341
+ const emptyResult = {
342
+ created: 0,
343
+ failed: 0,
344
+ skipped: 0,
345
+ total: 0,
346
+ failures: [],
347
+ results: [],
348
+ };
349
+ try {
350
+ this.logger?.log('Starting definition create operation');
351
+ const operationWarnings = [];
352
+ // Step 1: Resolve objects
353
+ const resolveResult = await this.resolveObjects(options, operationWarnings);
354
+ if (!resolveResult.success) {
355
+ return createFailureResult(emptyResult, resolveResult.errorCode, resolveResult.message, {
356
+ metadata: { duration: Date.now() - startTime },
357
+ });
358
+ }
359
+ const objectsBeforeLimit = this.applyMinRecordsThreshold(resolveResult.data, options, emptyResult, startTime);
360
+ if (!Array.isArray(objectsBeforeLimit))
361
+ return objectsBeforeLimit;
362
+ // Step 1b: Apply --limit to cap the number of objects processed
363
+ const { limited: objects, warning: objectLimitWarning } = this.applyObjectLimit(objectsBeforeLimit, options.limit);
364
+ if (objectLimitWarning) {
365
+ operationWarnings.push(objectLimitWarning);
366
+ }
367
+ // Step 2: Fetch record counts for resolved objects
368
+ const uniqueObjectNames = [...new Set(objects.map((o) => o.name))];
369
+ const countsResult = await this.filteringService.getRecordCounts(uniqueObjectNames);
370
+ const recordCounts = countsResult.success ? countsResult.data : new Map();
371
+ const method = options.method ?? 'metadata';
372
+ const year = options.year ?? new Date().getFullYear();
373
+ // Resolve year range: prefer explicit yearRange, fall back to year + usePrior
374
+ const yearRange = options.yearRange ?? {
375
+ entries: method === 'metadata' ? [] : [{ year, unbounded: options.usePrior ?? false }],
376
+ };
377
+ options.onProgress?.(`Checking existing definitions for ${objects.length} objects...`);
378
+ // Step 2.5: Build data availability grid (concurrent with Step 3)
379
+ let availabilityGrid;
380
+ if (this.dataAvailabilityService && yearRange.entries.length > 0) {
381
+ const gridResult = await this.dataAvailabilityService.buildGrid(uniqueObjectNames, yearRange);
382
+ if (gridResult.success) {
383
+ availabilityGrid = gridResult.data;
384
+ }
385
+ else {
386
+ this.logger?.log(`Data availability grid failed: ${gridResult.message ?? 'unknown'}`);
387
+ }
388
+ }
389
+ // REST API path: delegate to server when restClient is available.
390
+ // Fall back to the local path when:
391
+ // method='full' — server creates only 1 definition; local path composes all sub-methods
392
+ // lifetimePrimary=true — ISV Apex DefinitionFieldGenerationService has no lifetime-primary
393
+ // support (CLI-2944); local path pre-computes the lifetime filter
394
+ // JSON, name, timeCategory, and segmentCategory and persists them
395
+ // verbatim via create-definition. Remove this branch once the ISV
396
+ // Apex side mirrors the TS lifetime logic.
397
+ // timeCategory or segmentCategory override set — local path applies overrides verbatim through ctx builders (CLI-2957).
398
+ // CLI-3099: force local path for comparative + dateLiteralRange — the ISV create-smart
399
+ // endpoint ignores method=comparative for date literals and always builds Historical.
400
+ // The local path pre-computes SetA+SetB filterJson via buildComparativeDateLiteralFilterJson.
401
+ const useLocalPath = options.method === 'full' ||
402
+ options.lifetimePrimary === true ||
403
+ options.timeCategory !== undefined ||
404
+ options.segmentCategory !== undefined ||
405
+ (options.dateLiteralRange !== undefined && options.method === 'comparative');
406
+ if (this.restClient && !useLocalPath) {
407
+ return await this.executeCreationViaRest(objects, options, operationWarnings, startTime, availabilityGrid, recordCounts);
408
+ }
409
+ // Step 3: Check for existing definitions (local path — fallback when no REST client)
410
+ const existingDefsResult = await this.fetchAllExistingDefinitions();
411
+ if (!existingDefsResult.success) {
412
+ this.logger?.log('Failed to query existing definitions');
413
+ }
414
+ const existingDefinitions = existingDefsResult.success ? existingDefsResult.data : [];
415
+ const existingNames = new Set(existingDefinitions.map((def) => def.name));
416
+ // Step 4: Build candidate inputs
417
+ const candidateResult = await this.buildCandidateInputsForMethod(objects, method, year, yearRange, options, operationWarnings);
418
+ if (!candidateResult.success) {
419
+ return createFailureResult(emptyResult, candidateResult.errorCode, candidateResult.message, {
420
+ metadata: { duration: Date.now() - startTime },
421
+ });
422
+ }
423
+ const candidateInputs = candidateResult.data;
424
+ // Step 5: Deduplicate (partition into create vs skip)
425
+ const createInputsBeforeLimit = [];
426
+ const skippedInputs = [];
427
+ for (const input of candidateInputs) {
428
+ if (existingNames.has(input.name)) {
429
+ skippedInputs.push(input);
430
+ }
431
+ else {
432
+ createInputsBeforeLimit.push(input);
433
+ }
434
+ }
435
+ const skippedCount = skippedInputs.length;
436
+ if (createInputsBeforeLimit.length === 0) {
437
+ const totalDefs = candidateInputs.length;
438
+ if (totalDefs === 0) {
439
+ // No candidates generated (e.g., no record types found for --method recordtype)
440
+ return createFailureResult({ ...emptyResult, total: 0 }, CreateErrorCodes.NO_OBJECTS_FOUND, operationWarnings.length > 0
441
+ ? `No candidate definitions were generated: ${operationWarnings.join('; ')}`
442
+ : 'No candidate definitions were generated. Check object filters, record types, or method selection.', { metadata: { duration: Date.now() - startTime } });
443
+ }
444
+ this.logger?.log(`All ${totalDefs} definitions already exist`);
445
+ return createFailureResult({ ...emptyResult, skipped: skippedCount, total: totalDefs }, CreateErrorCodes.ALL_OBJECTS_SKIPPED, `All ${totalDefs} definitions already exist. Use 'sf cuneiform definition purge' to remove them first, then re-create.`, { metadata: { duration: Date.now() - startTime } });
446
+ }
447
+ this.logger?.log(`${createInputsBeforeLimit.length} definitions to create, ${skippedCount} already exist`);
448
+ // Apply --limit safety cap
449
+ const { limited: createInputs, warning: limitWarning } = this.applyInputLimit(createInputsBeforeLimit, options.limit);
450
+ if (limitWarning) {
451
+ operationWarnings.push(limitWarning);
452
+ }
453
+ const totalForPreview = createInputs.length + skippedCount;
454
+ options.onProgress?.(`${totalForPreview} ${totalForPreview === 1 ? 'definition' : 'definitions'} to create`);
455
+ // Step 6: Preview callback (unless dry-run)
456
+ const cancelResult = await DefinitionCreateOperation.invokePreviewCallback(options, createInputs, skippedInputs, candidateInputs.length, skippedCount, recordCounts, emptyResult, startTime);
457
+ if (cancelResult)
458
+ return cancelResult;
459
+ // Step 7: Dry run or create
460
+ if (options.dryRun) {
461
+ return this.buildDryRunResult(createInputs, skippedInputs, candidateInputs.length, operationWarnings, options, startTime, availabilityGrid, recordCounts);
462
+ }
463
+ return await this.executeCreation(createInputs, skippedInputs, candidateInputs.length, operationWarnings, options, startTime, availabilityGrid, recordCounts);
464
+ }
465
+ catch (error) {
466
+ const errorMessage = error instanceof Error ? error.message : String(error);
467
+ this.logger?.log(`Definition create operation failed: ${errorMessage}`);
468
+ return createFailureResult(emptyResult, CreateErrorCodes.OPERATION_FAILED, errorMessage, {
469
+ metadata: { duration: Date.now() - startTime },
470
+ });
471
+ }
472
+ }
473
+ // ── Private Instance Methods ─────────────────────────────────────────
474
+ /**
475
+ * Applies the --min-records threshold, returning the filtered list or an early failure result.
476
+ */
477
+ applyMinRecordsThreshold(objects, options, emptyResult, startTime) {
478
+ if (!options.minRecords || options.minRecords <= 0)
479
+ return objects;
480
+ const filtered = this.applyMinRecordsFilter(objects, options.minRecords);
481
+ if (filtered.length === 0) {
482
+ return createFailureResult(emptyResult, CreateErrorCodes.NO_OBJECTS_FOUND, `No objects found with at least ${options.minRecords} records`, { metadata: { duration: Date.now() - startTime } });
483
+ }
484
+ return filtered;
485
+ }
486
+ /**
487
+ * Builds record-type candidate inputs by querying the RecordTypeService for each object.
488
+ */
489
+ async buildRecordTypeCandidateInputs(objects, yearRange, options, warnings) {
490
+ if (!this.recordTypeService) {
491
+ return createFailureResult([], CreateErrorCodes.OPERATION_FAILED, 'RecordTypeService is required when method=recordtype');
492
+ }
493
+ const inputs = [];
494
+ const isSingleObject = objects.length === 1;
495
+ const rtStatus = options.recordTypeStatus ?? 'active';
496
+ for (const obj of objects) {
497
+ // eslint-disable-next-line no-await-in-loop -- Sequential per-object queries with per-object error handling
498
+ const rtResult = await this.recordTypeService.getRecordTypesByStatus(obj.name, rtStatus);
499
+ if (!rtResult.success) {
500
+ warnings.push(`Failed to query record types for ${obj.name}: ${rtResult.message}`);
501
+ continue;
502
+ }
503
+ let recordTypes = rtResult.data;
504
+ if (recordTypes.length === 0) {
505
+ const statusLabel = rtStatus === 'all' ? '' : ` ${rtStatus}`;
506
+ warnings.push(`Object '${obj.name}' has no${statusLabel} record types \u2014 skipping.`);
507
+ continue;
508
+ }
509
+ // Apply --recordtype filter (case-insensitive)
510
+ if (options.recordType) {
511
+ const targetLower = options.recordType.toLowerCase();
512
+ recordTypes = recordTypes.filter((rt) => rt.name.toLowerCase() === targetLower);
513
+ if (recordTypes.length === 0) {
514
+ if (isSingleObject) {
515
+ const available = rtResult.data.map((rt) => rt.name).join(', ');
516
+ return createFailureResult([], CreateErrorCodes.NO_OBJECTS_FOUND, `Record type '${options.recordType}' not found on ${obj.name}. Active record types: ${available}`);
517
+ }
518
+ warnings.push(`Object '${obj.name}' does not have record type '${options.recordType}' \u2014 skipping.`);
519
+ continue;
520
+ }
521
+ }
522
+ for (const rt of recordTypes) {
523
+ inputs.push(...DefinitionFieldGenerationService.buildInputsForRecordType(obj, rt.name, yearRange, options));
524
+ }
525
+ }
526
+ return createSuccessResult(inputs);
527
+ }
528
+ /**
529
+ * Builds full candidate inputs by composing metadata + historical + comparative + recordtype methods.
530
+ * Degrades gracefully to metadata + historical + comparative when RecordTypeService is absent.
531
+ */
532
+ async buildFullCandidateInputs(objects, year, yearRange, options, warnings) {
533
+ // Phase 1: Build metadata + historical + comparative inputs
534
+ const allInputs = [
535
+ ...DefinitionFieldGenerationService.buildCandidateInputs(objects, 'metadata', year, yearRange, options),
536
+ ...DefinitionFieldGenerationService.buildCandidateInputs(objects, 'historical', year, yearRange, options),
537
+ ...DefinitionFieldGenerationService.buildCandidateInputs(objects, 'comparative', year, yearRange, options),
538
+ ];
539
+ // Phase 1b: Build business process outcome inputs (always available — no service dependency)
540
+ // yearRange applies when user explicitly provided --year/--from/--to (options.year is set).
541
+ // Without explicit year flags, outcome defaults to lifetime (no year scoping).
542
+ const outcomeYearRange = options.year !== undefined ? yearRange : undefined;
543
+ allInputs.push(...DefinitionFieldGenerationService.buildOutcomeCandidateInputs(objects, options, warnings, outcomeYearRange));
544
+ // Phase 2: Build recordtype inputs (soft degradation if service absent)
545
+ if (!this.recordTypeService) {
546
+ warnings.push('RecordTypeService not available — full method degrading to metadata + historical + comparative + outcome only.');
547
+ return createSuccessResult(allInputs);
548
+ }
549
+ const rtResult = await this.buildRecordTypeCandidateInputs(objects, yearRange, options, warnings);
550
+ const rtInputs = rtResult.success ? rtResult.data : [];
551
+ if (!rtResult.success) {
552
+ warnings.push(`Record type inputs failed: ${rtResult.message ?? 'unknown error'} — using metadata + historical + comparative only.`);
553
+ }
554
+ // Phase 3: Merge and deduplicate by name (defensive — names are structurally distinct)
555
+ const seen = new Set();
556
+ const merged = [];
557
+ for (const input of [...allInputs, ...rtInputs]) {
558
+ if (!seen.has(input.name)) {
559
+ seen.add(input.name);
560
+ merged.push(input);
561
+ }
562
+ }
563
+ return createSuccessResult(merged);
564
+ }
565
+ /**
566
+ * Builds candidate inputs for any method, delegating to the appropriate builder.
567
+ */
568
+ async buildCandidateInputsForMethod(objects, method, year, yearRange, options, warnings) {
569
+ if (method === 'recordtype') {
570
+ return this.buildRecordTypeCandidateInputs(objects, yearRange, options, warnings);
571
+ }
572
+ if (method === 'outcome') {
573
+ // Only apply yearRange when user explicitly provided --year/--from/--to
574
+ const outcomeYR = options.year !== undefined ? yearRange : undefined;
575
+ return createSuccessResult(DefinitionFieldGenerationService.buildOutcomeCandidateInputs(objects, options, warnings, outcomeYR));
576
+ }
577
+ if (method === 'full') {
578
+ return this.buildFullCandidateInputs(objects, year, yearRange, options, warnings);
579
+ }
580
+ return createSuccessResult(DefinitionFieldGenerationService.buildCandidateInputs(objects, method, year, yearRange, options));
581
+ }
582
+ /**
583
+ * Builds a dry run result without creating any definitions.
584
+ */
585
+ buildDryRunResult(createInputs, skippedInputs, totalCount, warnings, options, startTime, availabilityGrid, recordCounts) {
586
+ // Build preview results from the inputs (fieldCount unavailable in dry runs)
587
+ const results = [];
588
+ for (const input of createInputs) {
589
+ results.push({
590
+ objectName: input.objectName,
591
+ objectLabel: input.objectLabel,
592
+ status: 'preview',
593
+ definitionName: input.name,
594
+ type: input.method,
595
+ category: input.category,
596
+ timeCategory: DefinitionCreateOperation.resolveTimeCategory(input),
597
+ segmentCategory: DefinitionCreateOperation.resolveSegmentCategory(input),
598
+ });
599
+ }
600
+ for (const input of skippedInputs) {
601
+ results.push({
602
+ objectName: input.objectName,
603
+ objectLabel: input.objectLabel,
604
+ status: 'preview',
605
+ definitionName: input.name,
606
+ type: DefinitionCreateOperation.derivePreviewType(options.method ?? 'metadata'),
607
+ category: input.category ?? DefinitionCreateOperation.derivePreviewCategory(options.method ?? 'metadata'),
608
+ timeCategory: DefinitionCreateOperation.resolveTimeCategory(input),
609
+ segmentCategory: DefinitionCreateOperation.resolveSegmentCategory(input),
610
+ });
611
+ }
612
+ // Fire callbacks — createInputs get 'preview', skippedInputs get 'skip' (progress display only;
613
+ // JSON result uses 'preview' for both so callers see a uniform dry-run output).
614
+ if (options.onObjectComplete) {
615
+ const createCount = createInputs.length;
616
+ for (let i = 0; i < results.length; i++) {
617
+ const r = results[i];
618
+ const isSkipped = i >= createCount;
619
+ options.onObjectComplete({
620
+ objectName: r.objectName,
621
+ status: isSkipped ? 'skip' : 'preview',
622
+ message: isSkipped ? 'definition already exists' : `would create "${r.definitionName}"`,
623
+ current: i + 1,
624
+ total: results.length,
625
+ type: r.type,
626
+ definitionName: r.definitionName,
627
+ definitionKey: r.definitionKey,
628
+ recordTypeName: r.segmentCategory,
629
+ category: r.category,
630
+ timeCategory: r.timeCategory,
631
+ segmentCategory: r.segmentCategory,
632
+ });
633
+ }
634
+ }
635
+ const dryRunResult = {
636
+ created: createInputs.length,
637
+ failed: 0,
638
+ skipped: skippedInputs.length,
639
+ total: totalCount,
640
+ dryRun: true,
641
+ failures: [],
642
+ results,
643
+ availabilityGrid,
644
+ recordCounts,
645
+ };
646
+ this.logger?.log(`Dry run: would create ${createInputs.length} definitions`);
647
+ return createSuccessResult(dryRunResult, {
648
+ message: `Dry run: would create ${createInputs.length} profiling definitions`,
649
+ warnings: warnings.length > 0 ? warnings : undefined,
650
+ metadata: { duration: Date.now() - startTime },
651
+ });
652
+ }
653
+ /**
654
+ * Executes sequential creation of definitions with per-item progress callbacks.
655
+ */
656
+ async executeCreation(createInputs, skippedInputs, totalCount, operationWarnings, options, startTime, availabilityGrid, recordCounts) {
657
+ const results = [];
658
+ const failures = [];
659
+ const totalItems = createInputs.length + skippedInputs.length;
660
+ let itemIndex = 0;
661
+ let createdCount = 0;
662
+ let failedCount = 0;
663
+ // Fire skipped items first
664
+ for (const input of skippedInputs) {
665
+ itemIndex++;
666
+ const r = {
667
+ objectName: input.objectName,
668
+ objectLabel: input.objectLabel,
669
+ status: 'skip',
670
+ definitionName: input.name,
671
+ type: input.method,
672
+ category: input.category,
673
+ timeCategory: DefinitionCreateOperation.resolveTimeCategory(input),
674
+ segmentCategory: DefinitionCreateOperation.resolveSegmentCategory(input),
675
+ };
676
+ results.push(r);
677
+ options.onObjectComplete?.({
678
+ objectName: r.objectName,
679
+ status: 'skip',
680
+ message: 'definition already exists',
681
+ current: itemIndex,
682
+ total: totalItems,
683
+ type: r.type,
684
+ definitionName: r.definitionName,
685
+ recordTypeName: r.segmentCategory,
686
+ category: r.category,
687
+ timeCategory: r.timeCategory,
688
+ segmentCategory: r.segmentCategory,
689
+ });
690
+ }
691
+ // Create definitions one at a time for real-time progress
692
+ for (const input of createInputs) {
693
+ itemIndex++;
694
+ // eslint-disable-next-line no-await-in-loop -- Sequential for real-time progress feedback
695
+ const createResult = await this.definitionService.createDefinition(input);
696
+ if (createResult.success && createResult.data) {
697
+ const def = createResult.data;
698
+ const fieldCount = createResult.metadata?.fieldCount ?? undefined;
699
+ createdCount++;
700
+ const r = {
701
+ objectName: input.objectName,
702
+ objectLabel: def.objectLabel ?? input.objectLabel,
703
+ status: 'success',
704
+ definitionName: def.name,
705
+ definitionId: def.id,
706
+ definitionKey: def.key,
707
+ type: input.method,
708
+ fieldCount,
709
+ category: def.category ?? input.category,
710
+ timeCategory: def.timeCategory ?? DefinitionCreateOperation.resolveTimeCategory(input),
711
+ segmentCategory: def.segmentCategory ?? DefinitionCreateOperation.resolveSegmentCategory(input),
712
+ };
713
+ results.push(r);
714
+ options.onObjectComplete?.({
715
+ objectName: r.objectName,
716
+ status: 'success',
717
+ message: DefinitionCreateOperation.formatObjectMessage(r),
718
+ current: itemIndex,
719
+ total: totalItems,
720
+ type: r.type,
721
+ definitionName: r.definitionName,
722
+ definitionKey: r.definitionKey,
723
+ recordTypeName: r.segmentCategory,
724
+ category: r.category,
725
+ timeCategory: r.timeCategory,
726
+ segmentCategory: r.segmentCategory,
727
+ fieldCount: r.fieldCount,
728
+ });
729
+ }
730
+ else {
731
+ failedCount++;
732
+ const errorMsg = createResult.message ?? 'Unknown error';
733
+ failures.push({
734
+ objectName: input.objectName,
735
+ error: errorMsg,
736
+ errorCode: createResult.errorCode ?? CreateErrorCodes.OPERATION_FAILED,
737
+ });
738
+ const r = {
739
+ objectName: input.objectName,
740
+ objectLabel: input.objectLabel,
741
+ status: 'fail',
742
+ definitionName: input.name,
743
+ type: input.method,
744
+ error: errorMsg,
745
+ category: input.category,
746
+ timeCategory: DefinitionCreateOperation.resolveTimeCategory(input),
747
+ segmentCategory: DefinitionCreateOperation.resolveSegmentCategory(input),
748
+ };
749
+ results.push(r);
750
+ options.onObjectComplete?.({
751
+ objectName: r.objectName,
752
+ status: 'fail',
753
+ message: errorMsg,
754
+ current: itemIndex,
755
+ total: totalItems,
756
+ type: r.type,
757
+ definitionName: r.definitionName,
758
+ recordTypeName: r.segmentCategory,
759
+ category: r.category,
760
+ timeCategory: r.timeCategory,
761
+ segmentCategory: r.segmentCategory,
762
+ });
763
+ }
764
+ }
765
+ const result = {
766
+ created: createdCount,
767
+ failed: failedCount,
768
+ skipped: skippedInputs.length,
769
+ total: totalCount,
770
+ failures,
771
+ results,
772
+ availabilityGrid,
773
+ recordCounts,
774
+ };
775
+ const duration = Date.now() - startTime;
776
+ this.logger?.log(`Created ${createdCount} definitions, ${failedCount} failed, ${skippedInputs.length} skipped`);
777
+ options.onProgress?.(`Complete: ${createdCount} created, ${failedCount} failed, ${skippedInputs.length} skipped`);
778
+ return createSuccessResult(result, {
779
+ message: `Created ${createdCount} profiling definitions`,
780
+ warnings: operationWarnings.length > 0 ? operationWarnings : undefined,
781
+ metadata: { duration },
782
+ });
783
+ }
784
+ /**
785
+ * Executes definition creation via the ISV REST API (create-smart endpoint).
786
+ * Server handles naming, categorization, deduplication, and creation.
787
+ * The CLI only provides objects, method, and options — no local business logic.
788
+ */
789
+ async executeCreationViaRest(objects, options, operationWarnings, startTime, availabilityGrid, recordCounts) {
790
+ const emptyResult = { created: 0, failed: 0, skipped: 0, total: 0, failures: [], results: [] };
791
+ this.logger?.log('Delegating definition creation to ISV REST API (create-smart)');
792
+ options.onProgress?.('Creating definitions via server-side pipeline...');
793
+ const method = options.method ?? 'metadata';
794
+ // Apply --limit safety cap before sending to ISV (ISV sees only the capped list).
795
+ const { limited: limitedObjects, warning: limitWarning } = this.applyObjectLimit(objects, options.limit);
796
+ if (limitWarning)
797
+ operationWarnings.push(limitWarning);
798
+ // Outcome pre-filter: only Opportunity, Case, Lead have outcome fields (CLI-1792).
799
+ const objectsToCreate = DefinitionCreateOperation.applyOutcomeFilter(limitedObjects, method, emptyResult, startTime);
800
+ if (!Array.isArray(objectsToCreate))
801
+ return objectsToCreate;
802
+ const restResult = await this.restClient.createSmart({
803
+ objects: objectsToCreate.map((o) => ({ name: o.name, label: o.label })),
804
+ method,
805
+ options: {
806
+ category: options.category,
807
+ timeCategory: options.timeCategory,
808
+ segmentCategory: options.segmentCategory,
809
+ year: options.year,
810
+ usePrior: options.usePrior,
811
+ noValueFrequency: options.noValueFrequency,
812
+ namePrefix: options.namePrefix,
813
+ // Prepend bullet separator — ISV joins suffix with a plain space, so we carry the bullet.
814
+ // CLI-3064: When --no-value-frequency is set, the resolved name on both client and server
815
+ // must include a "No Value Frequency" disambiguator \u2014 otherwise the value-frequency and
816
+ // no-value-frequency variants of the same (object, method, time-segment) collide on the
817
+ // name-keyed dedup gate and the second is silently skipped. The disambiguator is layered
818
+ // ahead of any user-supplied --name-suffix so user suffixes compose cleanly on top.
819
+ nameSuffix: DefinitionCreateOperation.composeRestNameSuffix(options.nameSuffix, options.noValueFrequency),
820
+ origin: options.origin,
821
+ recordType: options.recordType,
822
+ description: options.description,
823
+ dryRun: options.dryRun,
824
+ dateLiteralRange: options.dateLiteralRange,
825
+ yearEntries: options.yearRange?.entries.length
826
+ ? options.yearRange.entries.map(({ year, unbounded }) => ({ year, unbounded }))
827
+ : undefined,
828
+ },
829
+ });
830
+ if (!restResult.success) {
831
+ return createFailureResult(emptyResult, CreateErrorCodes.OPERATION_FAILED, restResult.message ?? 'REST API call failed', {
832
+ metadata: { duration: Date.now() - startTime },
833
+ });
834
+ }
835
+ const serverResponse = restResult.data;
836
+ const failures = [];
837
+ let createdCount = 0;
838
+ let failedCount = 0;
839
+ let skippedCount = 0;
840
+ // Map all server results synchronously, then enrich classification in parallel (CLI-1756).
841
+ const serverResults = serverResponse.results ?? [];
842
+ const resultPairs = serverResults.map((sr) => ({ sr, r: DefinitionCreateOperation.mapServerResult(sr) }));
843
+ // CLI-1756: ISV create-smart no longer returns classification fields (type, category,
844
+ // timeCategory, segmentCategory). Enrich all created definitions in parallel via GET
845
+ // so downstream consumers (JSON output, NUT assertions) see full classification metadata.
846
+ await this.enrichClassificationFields(resultPairs);
847
+ const results = [];
848
+ for (const { sr, r } of resultPairs) {
849
+ DefinitionCreateOperation.normalizeDryRunResult(r, sr, options.dryRun === true, method);
850
+ results.push(r);
851
+ if (sr.status === 'created' || sr.status === 'preview') {
852
+ createdCount++;
853
+ }
854
+ else if (sr.status === 'skipped') {
855
+ skippedCount++;
856
+ }
857
+ else if (sr.status === 'failed') {
858
+ failedCount++;
859
+ failures.push({
860
+ objectName: sr.objectName,
861
+ error: sr.errorMessage ?? 'Unknown error',
862
+ errorCode: CreateErrorCodes.OPERATION_FAILED,
863
+ });
864
+ }
865
+ DefinitionCreateOperation.notifyObjectComplete(r, sr, results.length, serverResults.length, options);
866
+ }
867
+ const createResult = {
868
+ created: createdCount,
869
+ failed: failedCount,
870
+ skipped: skippedCount,
871
+ total: serverResults.length,
872
+ dryRun: options.dryRun,
873
+ failures,
874
+ results,
875
+ availabilityGrid,
876
+ recordCounts,
877
+ };
878
+ return createSuccessResult(createResult, {
879
+ message: options.dryRun
880
+ ? `Preview: ${results.length} definitions`
881
+ : `Created ${createdCount} profiling definitions`,
882
+ warnings: operationWarnings.length > 0 ? operationWarnings : undefined,
883
+ metadata: { duration: Date.now() - startTime },
884
+ });
885
+ }
886
+ /**
887
+ * Enriches classification fields (type, category, timeCategory, segmentCategory) on created
888
+ * results in parallel. CLI-1756: ISV create-smart no longer returns these fields in its response.
889
+ */
890
+ async enrichClassificationFields(pairs) {
891
+ await Promise.all(pairs
892
+ .filter(({ sr, r }) => sr.status === 'created' && sr.definitionId && r.type === undefined)
893
+ .map(async ({ sr, r }) => {
894
+ const enrichResult = await this.definitionService.getDefinitionById(sr.definitionId);
895
+ if (enrichResult.success && enrichResult.data) {
896
+ const def = enrichResult.data;
897
+ // eslint-disable-next-line no-param-reassign -- enriching response object in-place (CLI-1756: ISV omits classification in create response)
898
+ r.type = def.type;
899
+ // eslint-disable-next-line no-param-reassign -- enriching response object in-place (CLI-1756)
900
+ r.category = def.category;
901
+ // eslint-disable-next-line no-param-reassign -- enriching response object in-place (CLI-1756)
902
+ r.timeCategory = def.timeCategory;
903
+ // eslint-disable-next-line no-param-reassign -- enriching response object in-place (CLI-1756)
904
+ r.segmentCategory = def.segmentCategory;
905
+ }
906
+ else {
907
+ this.logger?.log(`CLI-1756: Failed to enrich classification for ${sr.objectName}: ${enrichResult.message ?? 'unknown'}`);
908
+ }
909
+ }));
910
+ }
911
+ /**
912
+ * Resolves objects by explicit names, profiled set, or filtering criteria.
913
+ */
914
+ async resolveObjects(options, warnings) {
915
+ if (options.profiled) {
916
+ return this.resolveProfiledObjects(options, warnings);
917
+ }
918
+ if (options.objects && options.objects.length > 0) {
919
+ return this.resolveExplicitObjects(options.objects, warnings, options.onProgress);
920
+ }
921
+ return this.resolveFilteredObjects(options);
922
+ }
923
+ /**
924
+ * Resolves objects that have successful metadata profiling results.
925
+ */
926
+ async resolveProfiledObjects(options, warnings) {
927
+ options.onProgress?.('Querying profiled objects...');
928
+ this.logger?.log('Querying profiled objects from ProfilingSummaryService');
929
+ if (!this.profilingSummaryService) {
930
+ return createFailureResult([], CreateErrorCodes.OPERATION_FAILED, 'ProfilingSummaryService is required when profiled=true');
931
+ }
932
+ const profiledResult = await this.profilingSummaryService.queryProfiledObjects();
933
+ if (!profiledResult.success) {
934
+ return createFailureResult([], CreateErrorCodes.FILTER_FAILED, profiledResult.message);
935
+ }
936
+ let profiledNames = profiledResult.data;
937
+ if (profiledNames.length === 0) {
938
+ return createFailureResult([], CreateErrorCodes.NO_PROFILED_OBJECTS, 'No objects have been profiled yet. Run profiling with --method metadata first.');
939
+ }
940
+ this.logger?.log(`Found ${profiledNames.length} profiled objects`);
941
+ if (options.objects && options.objects.length > 0) {
942
+ const profiledSet = new Set(profiledNames.map((n) => n.toLowerCase()));
943
+ const intersected = [];
944
+ for (const obj of options.objects) {
945
+ if (profiledSet.has(obj.toLowerCase())) {
946
+ intersected.push(obj);
947
+ }
948
+ else {
949
+ warnings.push(`Object '${obj}' is not in the profiled set and will be skipped.`);
950
+ }
951
+ }
952
+ if (intersected.length === 0) {
953
+ return createFailureResult([], CreateErrorCodes.NO_PROFILED_OBJECTS, 'None of the specified objects have been profiled. Run profiling with --method metadata first.');
954
+ }
955
+ profiledNames = intersected;
956
+ }
957
+ options.onProgress?.(`Resolving ${profiledNames.length} profiled objects...`);
958
+ const resolveResult = await this.filteringService.getObjectsByName(profiledNames);
959
+ if (!resolveResult.success) {
960
+ return createFailureResult([], CreateErrorCodes.FILTER_FAILED, resolveResult.message);
961
+ }
962
+ if (resolveResult.warnings && resolveResult.warnings.length > 0) {
963
+ warnings.push(...resolveResult.warnings);
964
+ }
965
+ if (resolveResult.data.length === 0) {
966
+ return createFailureResult([], CreateErrorCodes.OBJECTS_NOT_FOUND, 'None of the profiled objects exist in the org');
967
+ }
968
+ let filtered = resolveResult.data;
969
+ if (options.filter && options.filter !== 'all') {
970
+ filtered = filtered.filter((obj) => (options.filter === 'custom' ? obj.isCustom : !obj.isCustom));
971
+ }
972
+ if (options.namespace) {
973
+ const ns = options.namespace.toLowerCase();
974
+ filtered = filtered.filter((obj) => obj.namespace?.toLowerCase() === ns);
975
+ }
976
+ if (options.pattern) {
977
+ const pattern = options.pattern;
978
+ if (pattern.includes('*')) {
979
+ const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$', 'i');
980
+ filtered = filtered.filter((obj) => regex.test(obj.name));
981
+ }
982
+ else {
983
+ const lower = pattern.toLowerCase();
984
+ filtered = filtered.filter((obj) => obj.name.toLowerCase().includes(lower));
985
+ }
986
+ }
987
+ if (filtered.length === 0) {
988
+ return createFailureResult([], CreateErrorCodes.NO_OBJECTS_FOUND, 'No profiled objects match the specified filters');
989
+ }
990
+ this.logger?.log(`Resolved ${filtered.length} profiled objects after filtering`);
991
+ return createSuccessResult(filtered);
992
+ }
993
+ /**
994
+ * Resolves objects by explicit API names.
995
+ */
996
+ async resolveExplicitObjects(objectNames, warnings, onProgress) {
997
+ onProgress?.('Resolving specified objects...');
998
+ this.logger?.log(`Resolving ${objectNames.length} explicitly specified objects`);
999
+ const resolveResult = await this.filteringService.getObjectsByName(objectNames);
1000
+ if (!resolveResult.success) {
1001
+ this.logger?.log(`Object resolution failed: ${resolveResult.message}`);
1002
+ return createFailureResult([], CreateErrorCodes.FILTER_FAILED, resolveResult.message);
1003
+ }
1004
+ if (resolveResult.warnings && resolveResult.warnings.length > 0) {
1005
+ // Surface "not found" warnings immediately via progress callback
1006
+ for (const w of resolveResult.warnings) {
1007
+ onProgress?.(w);
1008
+ }
1009
+ warnings.push(...resolveResult.warnings);
1010
+ }
1011
+ if (resolveResult.data.length === 0) {
1012
+ const notFoundNames = objectNames.join(', ');
1013
+ this.logger?.log(`None of the specified objects exist in the org: ${notFoundNames}`);
1014
+ return createFailureResult([], CreateErrorCodes.OBJECTS_NOT_FOUND, `None of the specified objects exist in the org: ${notFoundNames}`);
1015
+ }
1016
+ this.logger?.log(`Resolved ${resolveResult.data.length} of ${objectNames.length} specified objects`);
1017
+ return createSuccessResult(resolveResult.data);
1018
+ }
1019
+ /**
1020
+ * Resolves objects by filtering criteria.
1021
+ */
1022
+ async resolveFilteredObjects(options) {
1023
+ options.onProgress?.('Filtering objects...');
1024
+ const filterOptions = {
1025
+ type: options.filter,
1026
+ namespace: options.namespace,
1027
+ classification: options.classification,
1028
+ withRecords: options.minRecords && options.minRecords > 0 ? true : options.withRecords,
1029
+ withoutRecords: options.withoutRecords,
1030
+ hasRecordTypes: options.withRecordTypes,
1031
+ // CLI-3085: __mdt and other non-layoutable system objects (history/share/feed/big/platform-event)
1032
+ // are never valid profiling targets — opt in to the in-memory layoutable + keyPrefix predicate
1033
+ // unconditionally so the create flow stays tight regardless of classification path behavior.
1034
+ excludeSystemObjects: true,
1035
+ };
1036
+ if (options.pattern) {
1037
+ filterOptions.nameFilter = {
1038
+ value: options.pattern,
1039
+ operator: options.pattern.includes('*') ? 'wildcard' : 'contains',
1040
+ };
1041
+ }
1042
+ const filterResult = await this.filteringService.filter(filterOptions);
1043
+ if (!filterResult.success) {
1044
+ this.logger?.log(`Object filtering failed: ${filterResult.message}`);
1045
+ return createFailureResult([], CreateErrorCodes.FILTER_FAILED, filterResult.message);
1046
+ }
1047
+ if (filterResult.data.length === 0) {
1048
+ this.logger?.log('No objects found matching the specified filters');
1049
+ return createFailureResult([], CreateErrorCodes.NO_OBJECTS_FOUND, 'No objects found matching the specified filters');
1050
+ }
1051
+ this.logger?.log(`Found ${filterResult.data.length} objects matching filters`);
1052
+ return createSuccessResult(filterResult.data);
1053
+ }
1054
+ /**
1055
+ * Filters objects by minimum record count threshold.
1056
+ */
1057
+ applyMinRecordsFilter(objects, minRecords) {
1058
+ const filtered = objects.filter((obj) => (obj.recordCount ?? 0) >= minRecords);
1059
+ this.logger?.log(`After min-records filter (>=${minRecords}): ${filtered.length} of ${objects.length} objects remain`);
1060
+ return filtered;
1061
+ }
1062
+ /**
1063
+ * Applies a safety cap to the number of definition inputs to process.
1064
+ */
1065
+ applyInputLimit(inputs, limit) {
1066
+ if (!limit || limit <= 0 || inputs.length <= limit) {
1067
+ return { limited: inputs };
1068
+ }
1069
+ this.logger?.log(`Applied limit: ${limit} of ${inputs.length} definitions`);
1070
+ return {
1071
+ limited: inputs.slice(0, limit),
1072
+ warning: `Results limited to ${limit} definitions (${inputs.length} matched). Use --limit to increase.`,
1073
+ };
1074
+ }
1075
+ /**
1076
+ * Applies a safety cap to the number of SObjects sent to the ISV REST API.
1077
+ * Mirrors applyInputLimit for the REST path where objects are capped before the ISV call.
1078
+ */
1079
+ applyObjectLimit(objects, limit) {
1080
+ if (!limit || limit <= 0 || objects.length <= limit) {
1081
+ return { limited: objects };
1082
+ }
1083
+ this.logger?.log(`Applied object limit: ${limit} of ${objects.length} objects`);
1084
+ return {
1085
+ limited: objects.slice(0, limit),
1086
+ warning: `Results limited to ${limit} definitions (${objects.length} matched). Use --limit to increase.`,
1087
+ };
1088
+ }
1089
+ /**
1090
+ * Fetches all existing profiling definitions using pagination.
1091
+ */
1092
+ async fetchAllExistingDefinitions() {
1093
+ const allDefinitions = [];
1094
+ let offset = 0;
1095
+ const pageSize = MAX_PAGINATION_LIMIT;
1096
+ // eslint-disable-next-line no-constant-condition -- Pagination loop exits on short page or failure
1097
+ while (true) {
1098
+ // eslint-disable-next-line no-await-in-loop -- Sequential pagination: each page depends on knowing if more exist
1099
+ const pageResult = await this.definitionService.getDefinitions({ limit: pageSize, offset });
1100
+ if (!pageResult.success) {
1101
+ if (allDefinitions.length > 0) {
1102
+ this.logger?.log(`Pagination failed at offset ${offset}, using ${allDefinitions.length} definitions fetched so far`);
1103
+ return createSuccessResult(allDefinitions, {
1104
+ warnings: [`Pagination incomplete: failed at offset ${offset}. Deduplication may be partial.`],
1105
+ });
1106
+ }
1107
+ return pageResult;
1108
+ }
1109
+ allDefinitions.push(...pageResult.data);
1110
+ if (pageResult.data.length < pageSize) {
1111
+ break;
1112
+ }
1113
+ offset += pageSize;
1114
+ }
1115
+ this.logger?.log(`Fetched ${allDefinitions.length} total existing definitions across pagination`);
1116
+ return createSuccessResult(allDefinitions, {
1117
+ message: `Found ${allDefinitions.length} existing definitions`,
1118
+ });
1119
+ }
1120
+ }
1121
+ //# sourceMappingURL=DefinitionCreateOperation.js.map