@servicenow/sdk-build-plugins 4.2.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (349) hide show
  1. package/dist/acl-plugin.js +11 -0
  2. package/dist/acl-plugin.js.map +1 -1
  3. package/dist/applicability-plugin.d.ts +2 -0
  4. package/dist/applicability-plugin.js +72 -0
  5. package/dist/applicability-plugin.js.map +1 -0
  6. package/dist/atf/test-plugin.js +5 -2
  7. package/dist/atf/test-plugin.js.map +1 -1
  8. package/dist/basic-syntax-plugin.js +7 -1
  9. package/dist/basic-syntax-plugin.js.map +1 -1
  10. package/dist/business-rule-plugin.js +1 -0
  11. package/dist/business-rule-plugin.js.map +1 -1
  12. package/dist/call-expression-plugin.js +1 -107
  13. package/dist/call-expression-plugin.js.map +1 -1
  14. package/dist/column/column-to-record.d.ts +10 -3
  15. package/dist/column/column-to-record.js +44 -7
  16. package/dist/column/column-to-record.js.map +1 -1
  17. package/dist/column-plugin.d.ts +3 -1
  18. package/dist/column-plugin.js +12 -12
  19. package/dist/column-plugin.js.map +1 -1
  20. package/dist/dashboard/dashboard-component-property-defaults.d.ts +152 -0
  21. package/dist/dashboard/dashboard-component-property-defaults.js +264 -0
  22. package/dist/dashboard/dashboard-component-property-defaults.js.map +1 -0
  23. package/dist/dashboard/dashboard-component-resolver.d.ts +13 -0
  24. package/dist/dashboard/dashboard-component-resolver.js +69 -0
  25. package/dist/dashboard/dashboard-component-resolver.js.map +1 -0
  26. package/dist/dashboard/dashboard-plugin.d.ts +12 -0
  27. package/dist/dashboard/dashboard-plugin.js +397 -0
  28. package/dist/dashboard/dashboard-plugin.js.map +1 -0
  29. package/dist/data-plugin.d.ts +3 -0
  30. package/dist/data-plugin.js +61 -113
  31. package/dist/data-plugin.js.map +1 -1
  32. package/dist/email-notification-plugin.d.ts +2 -0
  33. package/dist/email-notification-plugin.js +541 -0
  34. package/dist/email-notification-plugin.js.map +1 -0
  35. package/dist/flow/constants/flow-plugin-constants.d.ts +58 -0
  36. package/dist/flow/constants/flow-plugin-constants.js +70 -0
  37. package/dist/flow/constants/flow-plugin-constants.js.map +1 -0
  38. package/dist/flow/flow-logic/flow-logic-constants.d.ts +38 -0
  39. package/dist/flow/flow-logic/flow-logic-constants.js +118 -0
  40. package/dist/flow/flow-logic/flow-logic-constants.js.map +1 -0
  41. package/dist/flow/flow-logic/flow-logic-diagnostics.d.ts +19 -0
  42. package/dist/flow/flow-logic/flow-logic-diagnostics.js +503 -0
  43. package/dist/flow/flow-logic/flow-logic-diagnostics.js.map +1 -0
  44. package/dist/flow/flow-logic/flow-logic-plugin-helpers.d.ts +62 -0
  45. package/dist/flow/flow-logic/flow-logic-plugin-helpers.js +2092 -0
  46. package/dist/flow/flow-logic/flow-logic-plugin-helpers.js.map +1 -0
  47. package/dist/flow/flow-logic/flow-logic-plugin.d.ts +52 -0
  48. package/dist/flow/flow-logic/flow-logic-plugin.js +283 -0
  49. package/dist/flow/flow-logic/flow-logic-plugin.js.map +1 -0
  50. package/dist/flow/flow-logic/flow-logic-shapes.d.ts +104 -0
  51. package/dist/flow/flow-logic/flow-logic-shapes.js +201 -0
  52. package/dist/flow/flow-logic/flow-logic-shapes.js.map +1 -0
  53. package/dist/flow/plugins/approval-rules-plugin.d.ts +2 -0
  54. package/dist/flow/plugins/approval-rules-plugin.js +49 -0
  55. package/dist/flow/plugins/approval-rules-plugin.js.map +1 -0
  56. package/dist/flow/plugins/flow-action-definition-plugin.d.ts +2 -0
  57. package/dist/flow/plugins/flow-action-definition-plugin.js +286 -0
  58. package/dist/flow/plugins/flow-action-definition-plugin.js.map +1 -0
  59. package/dist/flow/plugins/flow-data-pill-plugin.d.ts +9 -0
  60. package/dist/flow/plugins/flow-data-pill-plugin.js +212 -0
  61. package/dist/flow/plugins/flow-data-pill-plugin.js.map +1 -0
  62. package/dist/flow/plugins/flow-definition-plugin.d.ts +2 -0
  63. package/dist/flow/plugins/flow-definition-plugin.js +1668 -0
  64. package/dist/flow/plugins/flow-definition-plugin.js.map +1 -0
  65. package/dist/flow/plugins/flow-diagnostics-plugin.d.ts +26 -0
  66. package/dist/flow/plugins/flow-diagnostics-plugin.js +217 -0
  67. package/dist/flow/plugins/flow-diagnostics-plugin.js.map +1 -0
  68. package/dist/flow/plugins/flow-instance-plugin.d.ts +12 -0
  69. package/dist/flow/plugins/flow-instance-plugin.js +1205 -0
  70. package/dist/flow/plugins/flow-instance-plugin.js.map +1 -0
  71. package/dist/flow/plugins/flow-trigger-instance-plugin.d.ts +2 -0
  72. package/dist/flow/plugins/flow-trigger-instance-plugin.js +338 -0
  73. package/dist/flow/plugins/flow-trigger-instance-plugin.js.map +1 -0
  74. package/dist/flow/plugins/inline-script-plugin.d.ts +39 -0
  75. package/dist/flow/plugins/inline-script-plugin.js +80 -0
  76. package/dist/flow/plugins/inline-script-plugin.js.map +1 -0
  77. package/dist/flow/plugins/step-definition-plugin.d.ts +5 -0
  78. package/dist/flow/plugins/step-definition-plugin.js +71 -0
  79. package/dist/flow/plugins/step-definition-plugin.js.map +1 -0
  80. package/dist/flow/plugins/step-instance-plugin.d.ts +31 -0
  81. package/dist/flow/plugins/step-instance-plugin.js +339 -0
  82. package/dist/flow/plugins/step-instance-plugin.js.map +1 -0
  83. package/dist/flow/plugins/trigger-plugin.d.ts +2 -0
  84. package/dist/flow/plugins/trigger-plugin.js +96 -0
  85. package/dist/flow/plugins/trigger-plugin.js.map +1 -0
  86. package/dist/flow/plugins/wfa-datapill-plugin.d.ts +15 -0
  87. package/dist/flow/plugins/wfa-datapill-plugin.js +178 -0
  88. package/dist/flow/plugins/wfa-datapill-plugin.js.map +1 -0
  89. package/dist/flow/utils/approval-rules-processor.d.ts +13 -0
  90. package/dist/flow/utils/approval-rules-processor.js +267 -0
  91. package/dist/flow/utils/approval-rules-processor.js.map +1 -0
  92. package/dist/flow/utils/built-in-complex-objects.d.ts +19 -0
  93. package/dist/flow/utils/built-in-complex-objects.js +62 -0
  94. package/dist/flow/utils/built-in-complex-objects.js.map +1 -0
  95. package/dist/flow/utils/complex-object-resolver.d.ts +8 -0
  96. package/dist/flow/utils/complex-object-resolver.js +614 -0
  97. package/dist/flow/utils/complex-object-resolver.js.map +1 -0
  98. package/dist/flow/utils/complex-objects.d.ts +36 -0
  99. package/dist/flow/utils/complex-objects.js +481 -0
  100. package/dist/flow/utils/complex-objects.js.map +1 -0
  101. package/dist/flow/utils/data-pill-shapes.d.ts +58 -0
  102. package/dist/flow/utils/data-pill-shapes.js +135 -0
  103. package/dist/flow/utils/data-pill-shapes.js.map +1 -0
  104. package/dist/flow/utils/datapill-transformer.d.ts +110 -0
  105. package/dist/flow/utils/datapill-transformer.js +503 -0
  106. package/dist/flow/utils/datapill-transformer.js.map +1 -0
  107. package/dist/flow/utils/flow-constants.d.ts +72 -0
  108. package/dist/flow/utils/flow-constants.js +230 -0
  109. package/dist/flow/utils/flow-constants.js.map +1 -0
  110. package/dist/flow/utils/flow-io-to-record.d.ts +44 -0
  111. package/dist/flow/utils/flow-io-to-record.js +409 -0
  112. package/dist/flow/utils/flow-io-to-record.js.map +1 -0
  113. package/dist/flow/utils/flow-shapes.d.ts +161 -0
  114. package/dist/flow/utils/flow-shapes.js +255 -0
  115. package/dist/flow/utils/flow-shapes.js.map +1 -0
  116. package/dist/flow/utils/flow-to-xml.d.ts +16 -0
  117. package/dist/flow/utils/flow-to-xml.js +237 -0
  118. package/dist/flow/utils/flow-to-xml.js.map +1 -0
  119. package/dist/flow/utils/flow-variable-processor.d.ts +51 -0
  120. package/dist/flow/utils/flow-variable-processor.js +69 -0
  121. package/dist/flow/utils/flow-variable-processor.js.map +1 -0
  122. package/dist/flow/utils/label-cache-parser.d.ts +7 -0
  123. package/dist/flow/utils/label-cache-parser.js +24 -0
  124. package/dist/flow/utils/label-cache-parser.js.map +1 -0
  125. package/dist/flow/utils/label-cache-processor.d.ts +119 -0
  126. package/dist/flow/utils/label-cache-processor.js +719 -0
  127. package/dist/flow/utils/label-cache-processor.js.map +1 -0
  128. package/dist/flow/utils/pill-string-parser.d.ts +88 -0
  129. package/dist/flow/utils/pill-string-parser.js +306 -0
  130. package/dist/flow/utils/pill-string-parser.js.map +1 -0
  131. package/dist/flow/utils/schema-to-flow-object.d.ts +22 -0
  132. package/dist/flow/utils/schema-to-flow-object.js +318 -0
  133. package/dist/flow/utils/schema-to-flow-object.js.map +1 -0
  134. package/dist/flow/utils/service-catalog.d.ts +47 -0
  135. package/dist/flow/utils/service-catalog.js +137 -0
  136. package/dist/flow/utils/service-catalog.js.map +1 -0
  137. package/dist/flow/utils/utils.d.ts +117 -0
  138. package/dist/flow/utils/utils.js +345 -0
  139. package/dist/flow/utils/utils.js.map +1 -0
  140. package/dist/index.d.ts +20 -1
  141. package/dist/index.js +21 -1
  142. package/dist/index.js.map +1 -1
  143. package/dist/list-plugin.js +1 -1
  144. package/dist/list-plugin.js.map +1 -1
  145. package/dist/now-attach-plugin.d.ts +1 -0
  146. package/dist/now-attach-plugin.js +10 -10
  147. package/dist/now-attach-plugin.js.map +1 -1
  148. package/dist/now-ref-plugin.js +1 -1
  149. package/dist/now-ref-plugin.js.map +1 -1
  150. package/dist/record-plugin.d.ts +29 -0
  151. package/dist/record-plugin.js +66 -7
  152. package/dist/record-plugin.js.map +1 -1
  153. package/dist/repack/index.d.ts +2 -0
  154. package/dist/repack/index.js +8 -0
  155. package/dist/repack/index.js.map +1 -1
  156. package/dist/rest-api-plugin.js +54 -44
  157. package/dist/rest-api-plugin.js.map +1 -1
  158. package/dist/server-module-plugin/index.d.ts +10 -0
  159. package/dist/server-module-plugin/index.js +83 -59
  160. package/dist/server-module-plugin/index.js.map +1 -1
  161. package/dist/service-catalog/catalog-clientscript-plugin.d.ts +2 -0
  162. package/dist/service-catalog/catalog-clientscript-plugin.js +117 -0
  163. package/dist/service-catalog/catalog-clientscript-plugin.js.map +1 -0
  164. package/dist/service-catalog/catalog-item-plugin.d.ts +2 -0
  165. package/dist/service-catalog/catalog-item-plugin.js +115 -0
  166. package/dist/service-catalog/catalog-item-plugin.js.map +1 -0
  167. package/dist/service-catalog/catalog-ui-policy-plugin.d.ts +2 -0
  168. package/dist/service-catalog/catalog-ui-policy-plugin.js +266 -0
  169. package/dist/service-catalog/catalog-ui-policy-plugin.js.map +1 -0
  170. package/dist/service-catalog/index.d.ts +5 -0
  171. package/dist/service-catalog/index.js +22 -0
  172. package/dist/service-catalog/index.js.map +1 -0
  173. package/dist/service-catalog/record-to-shape.d.ts +6 -0
  174. package/dist/service-catalog/record-to-shape.js +93 -0
  175. package/dist/service-catalog/record-to-shape.js.map +1 -0
  176. package/dist/service-catalog/sc-record-producer-plugin.d.ts +2 -0
  177. package/dist/service-catalog/sc-record-producer-plugin.js +140 -0
  178. package/dist/service-catalog/sc-record-producer-plugin.js.map +1 -0
  179. package/dist/service-catalog/service-catalog-base.d.ts +311 -0
  180. package/dist/service-catalog/service-catalog-base.js +542 -0
  181. package/dist/service-catalog/service-catalog-base.js.map +1 -0
  182. package/dist/service-catalog/service-catalog-diagnostics.d.ts +45 -0
  183. package/dist/service-catalog/service-catalog-diagnostics.js +172 -0
  184. package/dist/service-catalog/service-catalog-diagnostics.js.map +1 -0
  185. package/dist/service-catalog/shape-to-record.d.ts +8 -0
  186. package/dist/service-catalog/shape-to-record.js +235 -0
  187. package/dist/service-catalog/shape-to-record.js.map +1 -0
  188. package/dist/service-catalog/utils.d.ts +323 -0
  189. package/dist/service-catalog/utils.js +1216 -0
  190. package/dist/service-catalog/utils.js.map +1 -0
  191. package/dist/service-catalog/variable-helper.d.ts +43 -0
  192. package/dist/service-catalog/variable-helper.js +92 -0
  193. package/dist/service-catalog/variable-helper.js.map +1 -0
  194. package/dist/service-catalog/variable-set-plugin.d.ts +2 -0
  195. package/dist/service-catalog/variable-set-plugin.js +175 -0
  196. package/dist/service-catalog/variable-set-plugin.js.map +1 -0
  197. package/dist/service-catalog/variables-transform.d.ts +139 -0
  198. package/dist/service-catalog/variables-transform.js +403 -0
  199. package/dist/service-catalog/variables-transform.js.map +1 -0
  200. package/dist/sla/sla-validators.d.ts +61 -0
  201. package/dist/sla/sla-validators.js +224 -0
  202. package/dist/sla/sla-validators.js.map +1 -0
  203. package/dist/sla-plugin.d.ts +5 -0
  204. package/dist/sla-plugin.js +280 -0
  205. package/dist/sla-plugin.js.map +1 -0
  206. package/dist/static-content-plugin.js +25 -2
  207. package/dist/static-content-plugin.js.map +1 -1
  208. package/dist/table-plugin.js +32 -15
  209. package/dist/table-plugin.js.map +1 -1
  210. package/dist/ui-page-plugin.js +832 -19
  211. package/dist/ui-page-plugin.js.map +1 -1
  212. package/dist/ui-policy-plugin.js +5 -7
  213. package/dist/ui-policy-plugin.js.map +1 -1
  214. package/dist/utils.d.ts +10 -1
  215. package/dist/utils.js +16 -0
  216. package/dist/utils.js.map +1 -1
  217. package/dist/ux-list-menu-config-plugin.d.ts +2 -0
  218. package/dist/ux-list-menu-config-plugin.js +292 -0
  219. package/dist/ux-list-menu-config-plugin.js.map +1 -0
  220. package/dist/workspace-plugin/chrome-tab.d.ts +2 -0
  221. package/dist/workspace-plugin/chrome-tab.js +46 -0
  222. package/dist/workspace-plugin/chrome-tab.js.map +1 -0
  223. package/dist/workspace-plugin/constants.d.ts +52 -0
  224. package/dist/workspace-plugin/constants.js +56 -0
  225. package/dist/workspace-plugin/constants.js.map +1 -0
  226. package/dist/workspace-plugin/fluent-utils.d.ts +9 -0
  227. package/dist/workspace-plugin/fluent-utils.js +60 -0
  228. package/dist/workspace-plugin/fluent-utils.js.map +1 -0
  229. package/dist/workspace-plugin/page.d.ts +8 -0
  230. package/dist/workspace-plugin/page.js +108 -0
  231. package/dist/workspace-plugin/page.js.map +1 -0
  232. package/dist/workspace-plugin/screen.d.ts +1 -0
  233. package/dist/workspace-plugin/screen.js +38 -0
  234. package/dist/workspace-plugin/screen.js.map +1 -0
  235. package/dist/workspace-plugin/templates/index.d.ts +10 -0
  236. package/dist/workspace-plugin/templates/index.js +20 -0
  237. package/dist/workspace-plugin/templates/index.js.map +1 -0
  238. package/dist/workspace-plugin/templates/record-page-composition.d.ts +1 -0
  239. package/dist/workspace-plugin/templates/record-page-composition.js +4043 -0
  240. package/dist/workspace-plugin/templates/record-page-composition.js.map +1 -0
  241. package/dist/workspace-plugin/templates/record-page-data.d.ts +1 -0
  242. package/dist/workspace-plugin/templates/record-page-data.js +527 -0
  243. package/dist/workspace-plugin/templates/record-page-data.js.map +1 -0
  244. package/dist/workspace-plugin/templates/record-page-interalEventMappings.d.ts +1 -0
  245. package/dist/workspace-plugin/templates/record-page-interalEventMappings.js +39 -0
  246. package/dist/workspace-plugin/templates/record-page-interalEventMappings.js.map +1 -0
  247. package/dist/workspace-plugin/templates/record-page-layoutModel.d.ts +1 -0
  248. package/dist/workspace-plugin/templates/record-page-layoutModel.js +55 -0
  249. package/dist/workspace-plugin/templates/record-page-layoutModel.js.map +1 -0
  250. package/dist/workspace-plugin/templates/record-page-properties.d.ts +1 -0
  251. package/dist/workspace-plugin/templates/record-page-properties.js +135 -0
  252. package/dist/workspace-plugin/templates/record-page-properties.js.map +1 -0
  253. package/dist/workspace-plugin/templates/record-page.d.ts +3 -0
  254. package/dist/workspace-plugin/templates/record-page.js +8 -0
  255. package/dist/workspace-plugin/templates/record-page.js.map +1 -0
  256. package/dist/workspace-plugin.d.ts +2 -0
  257. package/dist/workspace-plugin.js +453 -0
  258. package/dist/workspace-plugin.js.map +1 -0
  259. package/package.json +10 -12
  260. package/src/acl-plugin.ts +16 -1
  261. package/src/applicability-plugin.ts +82 -0
  262. package/src/atf/test-plugin.ts +6 -3
  263. package/src/basic-syntax-plugin.ts +10 -1
  264. package/src/business-rule-plugin.ts +2 -1
  265. package/src/call-expression-plugin.ts +2 -130
  266. package/src/column/column-to-record.ts +54 -8
  267. package/src/column-plugin.ts +29 -13
  268. package/src/dashboard/dashboard-component-property-defaults.ts +277 -0
  269. package/src/dashboard/dashboard-component-resolver.ts +69 -0
  270. package/src/dashboard/dashboard-plugin.ts +450 -0
  271. package/src/data-plugin.ts +67 -139
  272. package/src/email-notification-plugin.ts +850 -0
  273. package/src/flow/constants/flow-plugin-constants.ts +79 -0
  274. package/src/flow/flow-logic/flow-logic-constants.ts +120 -0
  275. package/src/flow/flow-logic/flow-logic-diagnostics.ts +591 -0
  276. package/src/flow/flow-logic/flow-logic-plugin-helpers.ts +2550 -0
  277. package/src/flow/flow-logic/flow-logic-plugin.ts +337 -0
  278. package/src/flow/flow-logic/flow-logic-shapes.ts +215 -0
  279. package/src/flow/plugins/approval-rules-plugin.ts +48 -0
  280. package/src/flow/plugins/flow-action-definition-plugin.ts +295 -0
  281. package/src/flow/plugins/flow-data-pill-plugin.ts +258 -0
  282. package/src/flow/plugins/flow-definition-plugin.ts +2173 -0
  283. package/src/flow/plugins/flow-diagnostics-plugin.ts +280 -0
  284. package/src/flow/plugins/flow-instance-plugin.ts +1499 -0
  285. package/src/flow/plugins/flow-trigger-instance-plugin.ts +444 -0
  286. package/src/flow/plugins/inline-script-plugin.ts +83 -0
  287. package/src/flow/plugins/step-definition-plugin.ts +67 -0
  288. package/src/flow/plugins/step-instance-plugin.ts +431 -0
  289. package/src/flow/plugins/trigger-plugin.ts +95 -0
  290. package/src/flow/plugins/wfa-datapill-plugin.ts +213 -0
  291. package/src/flow/utils/approval-rules-processor.ts +298 -0
  292. package/src/flow/utils/built-in-complex-objects.ts +81 -0
  293. package/src/flow/utils/complex-object-resolver.ts +875 -0
  294. package/src/flow/utils/complex-objects.ts +656 -0
  295. package/src/flow/utils/data-pill-shapes.ts +165 -0
  296. package/src/flow/utils/datapill-transformer.ts +632 -0
  297. package/src/flow/utils/flow-constants.ts +285 -0
  298. package/src/flow/utils/flow-io-to-record.ts +533 -0
  299. package/src/flow/utils/flow-shapes.ts +296 -0
  300. package/src/flow/utils/flow-to-xml.ts +318 -0
  301. package/src/flow/utils/flow-variable-processor.ts +100 -0
  302. package/src/flow/utils/label-cache-parser.ts +37 -0
  303. package/src/flow/utils/label-cache-processor.ts +870 -0
  304. package/src/flow/utils/pill-string-parser.ts +375 -0
  305. package/src/flow/utils/schema-to-flow-object.ts +385 -0
  306. package/src/flow/utils/service-catalog.ts +174 -0
  307. package/src/flow/utils/utils.ts +395 -0
  308. package/src/index.ts +20 -1
  309. package/src/list-plugin.ts +1 -1
  310. package/src/now-attach-plugin.ts +14 -11
  311. package/src/now-ref-plugin.ts +1 -1
  312. package/src/record-plugin.ts +76 -11
  313. package/src/repack/index.ts +14 -0
  314. package/src/rest-api-plugin.ts +62 -50
  315. package/src/server-module-plugin/index.ts +112 -86
  316. package/src/service-catalog/catalog-clientscript-plugin.ts +140 -0
  317. package/src/service-catalog/catalog-item-plugin.ts +162 -0
  318. package/src/service-catalog/catalog-ui-policy-plugin.ts +324 -0
  319. package/src/service-catalog/index.ts +5 -0
  320. package/src/service-catalog/record-to-shape.ts +109 -0
  321. package/src/service-catalog/sc-record-producer-plugin.ts +201 -0
  322. package/src/service-catalog/service-catalog-base.ts +600 -0
  323. package/src/service-catalog/service-catalog-diagnostics.ts +254 -0
  324. package/src/service-catalog/shape-to-record.ts +279 -0
  325. package/src/service-catalog/utils.ts +1455 -0
  326. package/src/service-catalog/variable-helper.ts +135 -0
  327. package/src/service-catalog/variable-set-plugin.ts +197 -0
  328. package/src/service-catalog/variables-transform.ts +438 -0
  329. package/src/sla/sla-validators.ts +331 -0
  330. package/src/sla-plugin.ts +358 -0
  331. package/src/static-content-plugin.ts +25 -2
  332. package/src/table-plugin.ts +49 -16
  333. package/src/ui-page-plugin.ts +1063 -20
  334. package/src/ui-policy-plugin.ts +5 -9
  335. package/src/utils.ts +24 -1
  336. package/src/ux-list-menu-config-plugin.ts +312 -0
  337. package/src/workspace-plugin/chrome-tab.ts +44 -0
  338. package/src/workspace-plugin/constants.ts +53 -0
  339. package/src/workspace-plugin/fluent-utils.ts +60 -0
  340. package/src/workspace-plugin/page.ts +139 -0
  341. package/src/workspace-plugin/screen.ts +34 -0
  342. package/src/workspace-plugin/templates/index.ts +17 -0
  343. package/src/workspace-plugin/templates/record-page-composition.ts +4051 -0
  344. package/src/workspace-plugin/templates/record-page-data.ts +523 -0
  345. package/src/workspace-plugin/templates/record-page-interalEventMappings.ts +35 -0
  346. package/src/workspace-plugin/templates/record-page-layoutModel.ts +51 -0
  347. package/src/workspace-plugin/templates/record-page-properties.ts +131 -0
  348. package/src/workspace-plugin/templates/record-page.ts +6 -0
  349. package/src/workspace-plugin.ts +574 -0
@@ -0,0 +1,1668 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FlowDefinitionPlugin = void 0;
4
+ const sdk_build_core_1 = require("@servicenow/sdk-build-core");
5
+ const node_zlib_1 = require("node:zlib");
6
+ const arrow_function_plugin_1 = require("../../arrow-function-plugin");
7
+ const now_id_plugin_1 = require("../../now-id-plugin");
8
+ const flow_io_to_record_1 = require("../utils/flow-io-to-record");
9
+ const flow_constants_1 = require("../utils/flow-constants");
10
+ const flow_to_xml_1 = require("../utils/flow-to-xml");
11
+ const flow_logic_constants_1 = require("../flow-logic/flow-logic-constants");
12
+ const flow_trigger_instance_plugin_1 = require("./flow-trigger-instance-plugin");
13
+ const flow_logic_plugin_1 = require("../flow-logic/flow-logic-plugin");
14
+ const flow_instance_plugin_1 = require("./flow-instance-plugin");
15
+ const utils_1 = require("../utils/utils");
16
+ const utils_2 = require("../../utils");
17
+ const label_cache_processor_1 = require("../utils/label-cache-processor");
18
+ const label_cache_parser_1 = require("../utils/label-cache-parser");
19
+ const pill_string_parser_1 = require("../utils/pill-string-parser");
20
+ const complex_object_resolver_1 = require("../utils/complex-object-resolver");
21
+ const sdk_build_core_2 = require("@servicenow/sdk-build-core");
22
+ const flow_variable_processor_1 = require("../utils/flow-variable-processor");
23
+ const datapill_transformer_1 = require("../utils/datapill-transformer");
24
+ const flow_plugin_constants_1 = require("../constants/flow-plugin-constants");
25
+ const complex_object_resolver_2 = require("../utils/complex-object-resolver");
26
+ /** Field name for complex object collection arrays in JSON payload */
27
+ const COMPLEX_OBJECT_COLLECTION_FIELD = '$COCollectionField';
28
+ const flow_shapes_1 = require("../utils/flow-shapes");
29
+ // ============================================================================
30
+ // DATAPILL TRANSFORMATION ARCHITECTURE
31
+ // ============================================================================
32
+ // This section contains all datapill transformation logic for Flow Definitions.
33
+ // Datapills are placeholders in XML that reference other flow elements.
34
+ //
35
+ // TWO TYPES OF DATAPILLS:
36
+ //
37
+ // 1. **UUID-based pills** - References to action/subflow instances
38
+ // Format: {{uuid.property}}
39
+ // Example: {{f56a03c1-18f6-4f7b-9c61-0d4ff472b334.name}}
40
+ // Transforms to: actionInstance_1.name
41
+ // Uses: uuidToIdentifierMap built from instance variable names
42
+ //
43
+ // 2. **Semantic pills** - References to flow parameters
44
+ // Format: {{prefix.property}}
45
+ // Supported prefixes:
46
+ // - trigger: {{trigger.table_name}} → params.trigger.table_name
47
+ // - flow_variable: {{flow_variable.myVar}} → params.flowVariables.myVar
48
+ // - inputs: {{inputs.empName}} → params.inputs.empName (subflows only)
49
+ // - outputs: {{outputs.result}} → params.outputs.result (subflows only)
50
+ // - subflow: {{subflow.value}} → params.inputs.value (alias for inputs)
51
+ // Uses: convertPillStringToShape from pill-string-parser utility
52
+ //
53
+ // TRANSFORMATION STRATEGY:
54
+ // The transformDataPill function tries transformations in order:
55
+ // 1. Try UUID-based transformation (transformUuidBasedPill)
56
+ // 2. Try semantic transformation (convertPillStringToShape)
57
+ // 3. Return null if neither matches (keep original string value)
58
+ //
59
+ // This unified approach ensures all datapill types are handled consistently
60
+ // in a single location, making the code maintainable and extensible.
61
+ // ============================================================================
62
+ /**
63
+ * Traverse ancestors to find the topmost ArrowFunction and extract its parameter name
64
+ * This finds the ArrowFunction that's an argument to Flow/SubflowDefinition, ignoring nested
65
+ * ArrowFunctions from control flow APIs like If, ElseIf, ForEach.
66
+ *
67
+ * @param shape - The shape to start traversing from
68
+ * @returns The parameter name from the topmost ArrowFunction if found, otherwise undefined
69
+ */
70
+ function getArrowFunctionParamName(shape) {
71
+ try {
72
+ let currentNode = shape.getOriginalNode();
73
+ let topmostArrowFunction;
74
+ // Traverse up the tree to find ALL ArrowFunctions and keep the topmost one
75
+ while (currentNode) {
76
+ const arrowFunc = currentNode.getParentIfKind(sdk_build_core_1.ts.SyntaxKind.ArrowFunction);
77
+ if (arrowFunc) {
78
+ // Found an ArrowFunction, keep track of it as potentially the topmost
79
+ topmostArrowFunction = arrowFunc;
80
+ // Continue traversing to find if there's a parent ArrowFunction
81
+ currentNode = arrowFunc;
82
+ }
83
+ else {
84
+ // Try to go up one level
85
+ const parent = currentNode.getParent();
86
+ if (!parent || parent === currentNode) {
87
+ break;
88
+ }
89
+ currentNode = parent;
90
+ }
91
+ }
92
+ // Extract parameter name from the topmost ArrowFunction
93
+ if (topmostArrowFunction && 'getParameters' in topmostArrowFunction) {
94
+ const params = topmostArrowFunction.getParameters();
95
+ if (params && params.length > 0) {
96
+ const firstParam = params[0];
97
+ if (firstParam) {
98
+ const paramName = firstParam.getName();
99
+ if (paramName) {
100
+ return paramName;
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+ catch (_e) {
107
+ // If any error occurs during traversal, just return undefined to fallback to default
108
+ }
109
+ return undefined;
110
+ }
111
+ /**
112
+ * Recursively process a shape to find and transform datapills
113
+ * Handles nested ObjectShape and ArrayShape structures
114
+ *
115
+ * @param value - The shape to process
116
+ * @param uuidToIdentifierMap - Map of UUID to variable identifiers
117
+ * @param source - Source for shape creation
118
+ * @param diagnostics - Diagnostics for error reporting
119
+ * @param parameterName - Optional parameter name
120
+ * @param logger - Logger for error reporting
121
+ * @returns Object with transformed shape and propsChanged flag
122
+ */
123
+ function processShapeForDatapills(value, uuidToIdentifierMap, source, diagnostics, logger, parameterName) {
124
+ // Check if value is already a datapill shape (PropertyAccessShape or TemplateExpressionShape)
125
+ if (value.if(sdk_build_core_1.PropertyAccessShape) || value.if(sdk_build_core_1.TemplateExpressionShape)) {
126
+ return {
127
+ shape: value,
128
+ propsChanged: false, // Already a datapill, no transformation needed
129
+ };
130
+ }
131
+ // Handle StringShape - may contain datapills
132
+ if (value.isString()) {
133
+ const stringValue = value.as(sdk_build_core_1.StringShape).getValue();
134
+ const transformed = transformDataPill(stringValue, uuidToIdentifierMap, source, diagnostics, logger, parameterName);
135
+ if (transformed !== null) {
136
+ return {
137
+ shape: transformed,
138
+ propsChanged: true, // String was transformed into a datapill
139
+ };
140
+ }
141
+ return {
142
+ shape: value,
143
+ propsChanged: false,
144
+ };
145
+ }
146
+ // Handle ObjectShape - recursively process properties
147
+ if (value.is(sdk_build_core_1.ObjectShape) ||
148
+ value.is(sdk_build_core_1.TemplateValueShape) ||
149
+ value.is(flow_shapes_1.ApprovalRulesShape) ||
150
+ value.is(flow_shapes_1.ApprovalDueDateShape)) {
151
+ const objEntries = value.isObject() ? value.entries() : value.getTemplateValue().entries();
152
+ const transformedObj = {};
153
+ let objPropsChanged = false;
154
+ for (const entry of objEntries) {
155
+ const key = entry[0];
156
+ const propValue = entry[1];
157
+ const result = processShapeForDatapills(propValue, uuidToIdentifierMap, source, diagnostics, logger, parameterName);
158
+ transformedObj[key] = result.shape;
159
+ if (result.propsChanged) {
160
+ objPropsChanged = true;
161
+ }
162
+ }
163
+ // If any property changed, rebuild the ObjectShape
164
+ if (objPropsChanged) {
165
+ let newObjectShape;
166
+ if (value.is(sdk_build_core_1.TemplateValueShape)) {
167
+ newObjectShape = new sdk_build_core_1.TemplateValueShape({
168
+ source: value.getSource(),
169
+ value: transformedObj,
170
+ });
171
+ }
172
+ else if (value.is(flow_shapes_1.ApprovalDueDateShape)) {
173
+ newObjectShape = new flow_shapes_1.ApprovalDueDateShape({
174
+ source: value.getSource(),
175
+ value: transformedObj,
176
+ });
177
+ }
178
+ else if (value.is(flow_shapes_1.ApprovalRulesShape)) {
179
+ newObjectShape = new flow_shapes_1.ApprovalRulesShape({
180
+ source: value.getSource(),
181
+ value: transformedObj,
182
+ });
183
+ }
184
+ else {
185
+ newObjectShape = new sdk_build_core_1.ObjectShape({
186
+ source: value.getSource(),
187
+ properties: transformedObj,
188
+ });
189
+ }
190
+ return {
191
+ shape: newObjectShape,
192
+ propsChanged: true,
193
+ };
194
+ }
195
+ return {
196
+ shape: value,
197
+ propsChanged: false,
198
+ };
199
+ }
200
+ // Handle ArrayShape - recursively process elements
201
+ if (value instanceof sdk_build_core_2.ArrayShape) {
202
+ const elements = value.getElements();
203
+ const transformedElements = [];
204
+ let arrayPropsChanged = false;
205
+ for (const element of elements) {
206
+ const result = processShapeForDatapills(element, uuidToIdentifierMap, source, diagnostics, logger, parameterName);
207
+ transformedElements.push(result.shape);
208
+ if (result.propsChanged) {
209
+ arrayPropsChanged = true;
210
+ }
211
+ }
212
+ // If any element changed, rebuild the ArrayShape
213
+ if (arrayPropsChanged) {
214
+ const newArrayShape = new sdk_build_core_2.ArrayShape({
215
+ source: value.getSource(),
216
+ elements: transformedElements,
217
+ });
218
+ return {
219
+ shape: newArrayShape,
220
+ propsChanged: true,
221
+ };
222
+ }
223
+ return {
224
+ shape: value,
225
+ propsChanged: false,
226
+ };
227
+ }
228
+ // For any other shape type, pass through
229
+ return {
230
+ shape: value,
231
+ propsChanged: false,
232
+ };
233
+ }
234
+ /**
235
+ * Transform data pill expressions in string values
236
+ * Handles two types of datapills:
237
+ * 1. UUID-based pills: {{uuid.property}} → references to action/subflow instances (e.g., actionInstance_1.name)
238
+ * 2. Semantic pills: {{trigger.property}}, {{flow_variable.name}} → references to params (e.g., params.trigger.name)
239
+ *
240
+ * @param stringValue - String that may contain datapill patterns
241
+ * @param uuidToIdentifierMap - Map of UUID to variable identifiers (for action/subflow references)
242
+ * @param source - Source for shape creation
243
+ * @param diagnostics - Diagnostics for error reporting
244
+ * @param parameterName - Optional parameter name to use instead of "params" (e.g., from ArrowFunction)
245
+ * @returns Transformed shape or null if no transformation needed
246
+ */
247
+ /**
248
+ * Wrap a PropertyAccessShape or IdentifierShape with wfa.dataPill(expression, 'type') call
249
+ * This creates a CallExpressionShape that wraps the expression
250
+ *
251
+ * @param expression - The PropertyAccessShape or IdentifierShape to wrap
252
+ * @param source - Source for shape creation
253
+ * @param dataType - The data type string (default: 'string')
254
+ * @returns CallExpressionShape wrapping the expression with wfa.dataPill()
255
+ */
256
+ function wrapWithDataPillCall(expression, source, dataType = 'string') {
257
+ return new sdk_build_core_1.CallExpressionShape({
258
+ source,
259
+ callee: 'wfa.dataPill',
260
+ args: [expression, new sdk_build_core_1.StringLiteralShape({ source, literalText: dataType })],
261
+ });
262
+ }
263
+ /**
264
+ * Extract all datapill names from a string value containing datapill patterns
265
+ * Handles both UUID-based pills ({{uuid.property}}) and semantic pills ({{prefix.path}})
266
+ *
267
+ * @param stringValue - String that may contain datapill patterns
268
+ * @returns Array of datapill names (e.g., ["trigger.table_name", "uuid.record.number"])
269
+ */
270
+ function extractDataPillNames(stringValue) {
271
+ const dataPillNames = [];
272
+ // Match all datapill patterns: {{...}}
273
+ const pillPattern = /\{\{([^}]+)\}\}/g;
274
+ const matches = Array.from(stringValue.matchAll(pillPattern));
275
+ for (const match of matches) {
276
+ if (match[1]) {
277
+ // Extract the content inside {{}} and split by | to get just the name part
278
+ // (some pills may have type info like {{pill.name|string}})
279
+ const pillContent = match[1].split('|')[0];
280
+ if (pillContent) {
281
+ dataPillNames.push(pillContent);
282
+ }
283
+ }
284
+ }
285
+ return dataPillNames;
286
+ }
287
+ /**
288
+ * Wrap all PropertyAccessShape expressions in a TemplateExpressionShape with wfa.dataPill()
289
+ * Creates a new TemplateExpressionShape with wrapped expressions in each span
290
+ *
291
+ * @param templateExpr - The TemplateExpressionShape, PropertyAccessShape, or IdentifierShape to process
292
+ * @param source - Source for shape creation
293
+ * @param labelCacheMap - Optional map of datapill names to their types
294
+ * @param originalString - Optional original string value to extract datapill name from
295
+ * @returns New TemplateExpressionShape with wrapped expressions
296
+ */
297
+ function wrapWithWfaDataPillExpression(templateExpr, source, labelCacheMap, originalString) {
298
+ // Extract all datapill names from the original string
299
+ const dataPillNames = originalString ? extractDataPillNames(originalString) : [];
300
+ if (templateExpr.is(sdk_build_core_1.PropertyAccessShape)) {
301
+ let dataType = 'string';
302
+ if (labelCacheMap && dataPillNames.length > 0) {
303
+ // For a single PropertyAccessShape, use the first (and likely only) datapill name
304
+ const firstPillName = dataPillNames[0];
305
+ if (firstPillName) {
306
+ // labelCacheMap returns the type string directly, not an object
307
+ dataType = labelCacheMap.get(firstPillName) || 'string';
308
+ }
309
+ }
310
+ return wrapWithDataPillCall(templateExpr, source, dataType);
311
+ }
312
+ if (templateExpr.is(sdk_build_core_1.IdentifierShape)) {
313
+ return wrapWithDataPillCall(templateExpr, source);
314
+ }
315
+ const originalSpans = templateExpr.getSpans();
316
+ const wrappedSpans = [];
317
+ let pillIndex = 0;
318
+ for (const span of originalSpans) {
319
+ const expression = span.getExpression();
320
+ const literalText = span.getLiteralText();
321
+ // Wrap the expression with wfa.dataPill() if it's a PropertyAccessShape or IdentifierShape
322
+ if (expression instanceof sdk_build_core_1.PropertyAccessShape || expression instanceof sdk_build_core_1.IdentifierShape) {
323
+ let dataType = 'string';
324
+ if (labelCacheMap && pillIndex < dataPillNames.length) {
325
+ // Use the corresponding datapill name for this expression
326
+ const pillName = dataPillNames[pillIndex];
327
+ if (pillName) {
328
+ // labelCacheMap returns the type string directly, not an object
329
+ dataType = labelCacheMap.get(pillName) || 'string';
330
+ }
331
+ pillIndex++;
332
+ }
333
+ const wrappedExpr = wrapWithDataPillCall(expression, source, dataType);
334
+ wrappedSpans.push(new sdk_build_core_1.TemplateSpanShape({
335
+ source,
336
+ expression: wrappedExpr,
337
+ literalText,
338
+ }));
339
+ }
340
+ else {
341
+ // Keep as-is if not a PropertyAccessShape or IdentifierShape
342
+ wrappedSpans.push(span);
343
+ }
344
+ }
345
+ return new sdk_build_core_1.TemplateExpressionShape({
346
+ source,
347
+ literalText: templateExpr.getLiteralText(),
348
+ spans: wrappedSpans,
349
+ });
350
+ }
351
+ /**
352
+ * Extract all datapills (both UUID-based and semantic) from a string.
353
+ * Uses a single regex to find all {{...}} patterns, then determines type using conditional logic.
354
+ *
355
+ * @param stringValue - String that may contain datapill patterns
356
+ * @param uuidToIdentifierMap - Map of UUID to variable identifiers (includes forEach parameter names)
357
+ * @param source - Source for shape creation
358
+ * @param diagnostics - Diagnostics for error reporting
359
+ * @param parameterName - Parameter name for semantic pills (default 'params')
360
+ * @returns Array of pills with their positions and transformed expressions
361
+ */
362
+ function extractAllPills(stringValue, uuidToIdentifierMap, source, _diagnostics, parameterName) {
363
+ const pills = [];
364
+ // SINGLE regex to find ALL pill patterns: {{anything}}
365
+ const pillRegex = /\{\{([^}]+)\}\}/g;
366
+ // Loop through ALL matches
367
+ for (const match of stringValue.matchAll(pillRegex)) {
368
+ const fullMatch = match[0]; // e.g., "{{uuid.field}}" or "{{trigger.name}}"
369
+ const content = match[1]; // e.g., "uuid.field" or "trigger.name"
370
+ if (!content) {
371
+ continue;
372
+ }
373
+ const matchStart = match.index ?? 0;
374
+ const matchEnd = matchStart + fullMatch.length;
375
+ // Try UUID pattern first (more specific)
376
+ // UUID format: 8-4-4-4-12 hex digits followed by dot and property path
377
+ const uuidMatch = content.match(/^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.([a-zA-Z_][a-zA-Z0-9_.]*[a-zA-Z0-9_])$/);
378
+ if (uuidMatch) {
379
+ // This is a UUID-based pill
380
+ const uuid = uuidMatch[1];
381
+ const property = uuidMatch[2];
382
+ if (!uuid || !property) {
383
+ continue;
384
+ }
385
+ const identifier = uuidToIdentifierMap.get(uuid);
386
+ if (identifier) {
387
+ // PRESERVE EXISTING LOGIC: Apply forEach parameter handling
388
+ const isForEachParam = isForEachParameter(identifier, uuid);
389
+ let expression;
390
+ if (isForEachParam) {
391
+ // Special case for forEach: if property is exactly 'item', return just the identifier
392
+ if (property === 'item') {
393
+ expression = identifier;
394
+ }
395
+ else if (property.startsWith('item.')) {
396
+ // Strip 'item.' prefix for forEach parameters
397
+ const propertyPath = property.substring(5);
398
+ expression = new sdk_build_core_1.PropertyAccessShape({
399
+ source,
400
+ elements: [identifier, propertyPath],
401
+ });
402
+ }
403
+ else {
404
+ // Property doesn't start with 'item.' - preserve as is
405
+ expression = new sdk_build_core_1.PropertyAccessShape({
406
+ source,
407
+ elements: [identifier, property],
408
+ });
409
+ }
410
+ }
411
+ else {
412
+ // NOT a forEach parameter - preserve full property path
413
+ expression = new sdk_build_core_1.PropertyAccessShape({
414
+ source,
415
+ elements: [identifier, property],
416
+ });
417
+ }
418
+ pills.push({
419
+ matchStart,
420
+ matchEnd,
421
+ matchText: fullMatch,
422
+ expression,
423
+ type: 'uuid',
424
+ });
425
+ }
426
+ // If UUID not in map, skip this pill (existing behavior)
427
+ continue;
428
+ }
429
+ // Not a UUID pill - try semantic transformation
430
+ const parsed = (0, pill_string_parser_1.parseSinglePill)(fullMatch, true);
431
+ if (!parsed) {
432
+ // Invalid pill format - skip
433
+ continue;
434
+ }
435
+ if ((0, pill_string_parser_1.isUuidPrefix)(parsed.prefix)) {
436
+ // This is a UUID prefix but wasn't caught above - skip
437
+ continue;
438
+ }
439
+ const tsRoot = (0, pill_string_parser_1.mapPillPrefixToTsRoot)(parsed.prefix, parameterName);
440
+ if (!tsRoot) {
441
+ // Unknown prefix - skip
442
+ continue;
443
+ }
444
+ // Handle schema references (no property access) like {{flowVariables}} or {{outputs}}
445
+ let expression;
446
+ if (parsed.path === '') {
447
+ // Schema reference - tsRoot already contains full path
448
+ expression = (0, pill_string_parser_1.createPropertyAccessFromPath)(tsRoot, source);
449
+ }
450
+ else {
451
+ // Property access like {{trigger.table_name}}
452
+ const fullPath = `${tsRoot}.${parsed.path}`;
453
+ expression = (0, pill_string_parser_1.createPropertyAccessFromPath)(fullPath, source);
454
+ }
455
+ if (expression) {
456
+ pills.push({
457
+ matchStart,
458
+ matchEnd,
459
+ matchText: fullMatch,
460
+ expression,
461
+ type: 'semantic',
462
+ });
463
+ }
464
+ }
465
+ // Pills are already in order since we process matches sequentially
466
+ // No need to sort or remove duplicates - each match is processed once
467
+ return pills;
468
+ }
469
+ /**
470
+ * Build a TemplateExpressionShape from a list of pills with their positions.
471
+ * Preserves all text (leading, in-between, trailing) from the original string.
472
+ *
473
+ * @param stringValue - Original string containing pills and text
474
+ * @param pills - List of pills with positions (in order)
475
+ * @param source - Source for shape creation
476
+ * @returns TemplateExpressionShape with all pills and text
477
+ */
478
+ function buildTemplateExpression(stringValue, pills, source) {
479
+ const spans = [];
480
+ // Head: text before first pill (leading text)
481
+ const firstPill = pills[0];
482
+ if (!firstPill) {
483
+ // Should never happen, but TypeScript wants this check
484
+ throw new Error('buildTemplateExpression called with empty pills array');
485
+ }
486
+ const literalText = stringValue.substring(0, firstPill.matchStart);
487
+ // Create spans for each pill (handles 1, 2, 20, or any number of pills)
488
+ for (let i = 0; i < pills.length; i++) {
489
+ const pill = pills[i];
490
+ if (!pill) {
491
+ continue;
492
+ }
493
+ const nextPill = pills[i + 1];
494
+ // Text after this pill (in-between text or trailing text)
495
+ // - If there's a next pill: text between current and next pill
496
+ // - If this is the last pill: text after this pill to end of string (trailing)
497
+ const afterText = stringValue.substring(pill.matchEnd, nextPill ? nextPill.matchStart : stringValue.length);
498
+ spans.push(new sdk_build_core_1.TemplateSpanShape({
499
+ source,
500
+ expression: pill.expression,
501
+ literalText: afterText,
502
+ }));
503
+ }
504
+ return new sdk_build_core_1.TemplateExpressionShape({
505
+ source,
506
+ literalText, // head (leading text)
507
+ spans, // pills with in-between and trailing text
508
+ });
509
+ }
510
+ function transformDataPill(stringValue, uuidToIdentifierMap, source, diagnostics, logger, parameterName) {
511
+ // Special case: Schema references for SetFlowVariables/AssignSubflowOutputs
512
+ // {{flowVariables}} and {{outputs}} should remain as bare PropertyAccessShape without wrapping
513
+ if (stringValue === '{{flowVariables}}' || stringValue === '{{outputs}}') {
514
+ const allPills = extractAllPills(stringValue, uuidToIdentifierMap, source, diagnostics, parameterName);
515
+ if (allPills.length === 1 && allPills[0]?.expression.is(sdk_build_core_1.PropertyAccessShape)) {
516
+ return allPills[0].expression;
517
+ }
518
+ }
519
+ // Extract label_cache from source Record and create type map
520
+ let labelCacheMap;
521
+ try {
522
+ const labelCacheValue = source.get('label_cache')?.getValue();
523
+ if (labelCacheValue && typeof labelCacheValue === 'string') {
524
+ labelCacheMap = (0, label_cache_parser_1.createLableCacheNameToTypeMap)(labelCacheValue, logger);
525
+ }
526
+ }
527
+ catch (_error) {
528
+ // If label_cache extraction fails, continue with default 'string' type
529
+ labelCacheMap = undefined;
530
+ }
531
+ // Extract all pills (both UUID-based and semantic) from the string
532
+ const allPills = extractAllPills(stringValue, uuidToIdentifierMap, source, diagnostics, parameterName);
533
+ if (allPills.length === 0) {
534
+ return null; // No pills found
535
+ }
536
+ // Check if single standalone pill (optimization)
537
+ const firstPill = allPills[0];
538
+ if (allPills.length === 1 && firstPill && firstPill.matchStart === 0 && firstPill.matchEnd === stringValue.length) {
539
+ // Single pill covering entire string - return PropertyAccessShape/IdentifierShape directly
540
+ return wrapWithWfaDataPillExpression(firstPill.expression, source, labelCacheMap, stringValue);
541
+ }
542
+ // Build template expression from all pills
543
+ const templateExpr = buildTemplateExpression(stringValue, allPills, source);
544
+ return wrapWithWfaDataPillExpression(templateExpr, source, labelCacheMap, stringValue);
545
+ }
546
+ /**
547
+ * Helper function to check if a UUID corresponds to a forEach flow logic instance
548
+ * @param uuid - The UUID to check
549
+ * @returns true if the UUID maps to a forEach logic instance, false otherwise
550
+ */
551
+ function isForEachByUuid(uuid) {
552
+ const record = datapill_transformer_1.uuidToRecordMap.get(uuid);
553
+ if (record && record.getTable() === 'sys_hub_flow_logic_instance_v2') {
554
+ const logicDefId = record.get('logic_definition')?.ifString()?.getValue();
555
+ if (logicDefId) {
556
+ const logicName = flow_logic_constants_1.FlowLogicSysId.getLogicName(logicDefId);
557
+ return logicName === flow_logic_constants_1.FLOW_LOGIC.FOR_EACH;
558
+ }
559
+ }
560
+ return false;
561
+ }
562
+ /**
563
+ * Checks if an identifier is actually a forEach parameter by inspecting its AST context.
564
+ * This prevents incorrectly stripping 'item' from property paths when 'item' is an actual field name.
565
+ *
566
+ * @param identifier - The IdentifierShape to check
567
+ * @param uuid - Optional UUID of the flow logic instance (used during XML→Fluent)
568
+ * @returns true if the identifier is a forEach parameter, false otherwise
569
+ */
570
+ function isForEachParameter(identifier, uuid) {
571
+ const originalSource = identifier.getOriginalSource();
572
+ const identifierName = identifier.getName();
573
+ // Branch 1: XML → Fluent (originalSource is a Record)
574
+ if (!sdk_build_core_1.ts.Node.isNode(originalSource)) {
575
+ // Check if Record is a forEach logic definition
576
+ if (originalSource instanceof sdk_build_core_1.Record && originalSource.getTable() === 'sys_hub_flow_logic_v2') {
577
+ const logicDefId = originalSource.get('logic_definition')?.ifString()?.getValue();
578
+ if (logicDefId) {
579
+ const logicName = flow_logic_constants_1.FlowLogicSysId.getLogicName(logicDefId);
580
+ return logicName === flow_logic_constants_1.FLOW_LOGIC.FOR_EACH;
581
+ }
582
+ }
583
+ // Fallback: check name pattern for backwards compatibility
584
+ return /^item(_\d+)?$/.test(identifierName);
585
+ }
586
+ // Branch 2: Fluent → XML (originalSource is a ts.Node)
587
+ // Try AST-based detection first
588
+ const arrowFn = originalSource.getFirstAncestorByKind(sdk_build_core_1.ts.SyntaxKind.ArrowFunction);
589
+ if (arrowFn) {
590
+ const callExpr = arrowFn.getParentIfKind(sdk_build_core_1.ts.SyntaxKind.CallExpression);
591
+ if (callExpr) {
592
+ const callExprName = (0, utils_2.getCallExpressionName)(callExpr);
593
+ const isThirdArgument = callExpr.getArguments()[2] === arrowFn;
594
+ if (callExprName === flow_logic_constants_1.FLOW_LOGIC.FOR_EACH && isThirdArgument) {
595
+ return true; // AST check succeeded
596
+ }
597
+ }
598
+ }
599
+ // AST check failed or arrow function not found - use UUID fallback
600
+ return uuid ? isForEachByUuid(uuid) : false;
601
+ }
602
+ /**
603
+ * Clean up config object by removing uuid (if it matches sys_id) and empty string fields
604
+ *
605
+ * @param configShape - The config ObjectShape to clean up
606
+ * @param instanceShape - The instance shape (used to get the source record)
607
+ * @returns Cleaned up config shape or original if no cleanup needed
608
+ */
609
+ function cleanupConfigShape(configShape, instanceShape) {
610
+ if (!(configShape instanceof sdk_build_core_1.ObjectShape)) {
611
+ return configShape;
612
+ }
613
+ const configObj = configShape;
614
+ const uuid = configObj.get('uuid')?.ifString()?.getValue();
615
+ const sysIdShape = configObj.get('$id');
616
+ if (!uuid || !sysIdShape) {
617
+ return configShape;
618
+ }
619
+ // Get the sys_id value (could be a NowIdShape or string)
620
+ let sysId;
621
+ const instanceSource = instanceShape.getSource();
622
+ if (sysIdShape.if(now_id_plugin_1.NowIdShape)) {
623
+ sysId = instanceSource instanceof sdk_build_core_1.Record ? String(instanceSource.getId().getValue()) : undefined;
624
+ }
625
+ else if (sysIdShape.isString()) {
626
+ sysId = sysIdShape.asString().getValue();
627
+ }
628
+ // Only clean up if uuid matches the sys_id (after converting uuid to sys_id format)
629
+ if (!sysId || (0, utils_1.uuidToSysId)(uuid) !== sysId) {
630
+ return configShape;
631
+ }
632
+ // Create new config without uuid property and empty string values
633
+ const configEntries = configObj.entries();
634
+ const newConfigProps = {};
635
+ for (const [key, value] of configEntries) {
636
+ // Skip uuid field
637
+ if (key === 'uuid') {
638
+ continue;
639
+ }
640
+ // Skip fields with empty string values
641
+ if (value.isString() && value.asString().getValue() === '') {
642
+ continue;
643
+ }
644
+ newConfigProps[key] = value;
645
+ }
646
+ return new sdk_build_core_1.ObjectShape({
647
+ source: configObj.getSource(),
648
+ properties: newConfigProps,
649
+ });
650
+ }
651
+ const documentationRelationship = {
652
+ descendant: true,
653
+ via: { name: 'name', element: 'element' },
654
+ };
655
+ const complexObjectRelationship = {
656
+ descendant: true,
657
+ via: [flow_io_to_record_1.complexObjectMatchesIoRecord],
658
+ };
659
+ const inputOutputRelationships = {
660
+ via: 'model',
661
+ descendant: true,
662
+ relationships: {
663
+ sys_documentation: documentationRelationship,
664
+ sys_choice: {
665
+ via: { name: 'name', element: 'element' },
666
+ descendant: true,
667
+ },
668
+ sys_complex_object: complexObjectRelationship,
669
+ },
670
+ };
671
+ const variableRelationship = {
672
+ via: 'model',
673
+ descendant: true,
674
+ relationships: {
675
+ sys_documentation: documentationRelationship,
676
+ sys_complex_object: complexObjectRelationship,
677
+ },
678
+ };
679
+ const legacyRelationship = {
680
+ via: 'flow',
681
+ descendant: true,
682
+ relationships: {
683
+ sys_variable_value: {
684
+ via: 'document_key',
685
+ descendant: true,
686
+ },
687
+ sys_element_mapping: {
688
+ via: 'id',
689
+ descendant: true,
690
+ },
691
+ sys_hub_input_scripts: {
692
+ via: 'instance',
693
+ descendant: true,
694
+ },
695
+ },
696
+ };
697
+ const commonFlowRelationships = {
698
+ sys_hub_flow_input: inputOutputRelationships,
699
+ sys_hub_flow_output: inputOutputRelationships,
700
+ sys_hub_flow_variable: variableRelationship,
701
+ sys_hub_flow_stage: {
702
+ via: 'flow',
703
+ descendant: true,
704
+ },
705
+ sys_hub_action_instance: legacyRelationship,
706
+ sys_hub_sub_flow_instance: {
707
+ ...legacyRelationship,
708
+ relationships: {
709
+ ...legacyRelationship.relationships,
710
+ sys_hub_sub_flow_instance_inputs: {
711
+ via: 'model',
712
+ descendant: true,
713
+ },
714
+ },
715
+ },
716
+ sys_hub_trigger_instance: legacyRelationship,
717
+ sys_hub_flow_logic: {
718
+ via: 'flow',
719
+ descendant: true,
720
+ relationships: {
721
+ sys_element_mapping: {
722
+ via: 'id',
723
+ descendant: true,
724
+ },
725
+ sys_hub_flow_logic_ext_input: {
726
+ via: 'model',
727
+ descendant: true,
728
+ },
729
+ sys_hub_input_scripts: {
730
+ via: 'instance',
731
+ descendant: true,
732
+ },
733
+ },
734
+ },
735
+ sys_hub_pill_compound: {
736
+ via: 'attached_to',
737
+ descendant: true,
738
+ },
739
+ sys_hub_alias_mapping: {
740
+ via: 'source_id',
741
+ descendant: true,
742
+ },
743
+ sys_flow_cat_variable_model: {
744
+ via: 'id',
745
+ descendant: true,
746
+ relationships: {
747
+ sys_flow_cat_variable: {
748
+ via: 'flow_catalog_model',
749
+ descendant: true,
750
+ },
751
+ },
752
+ },
753
+ };
754
+ const commonInstanceV2Relationships = {
755
+ sys_hub_trigger_instance_v2: {
756
+ via: 'flow',
757
+ descendant: true,
758
+ },
759
+ sys_hub_action_instance_v2: {
760
+ via: 'flow',
761
+ descendant: true,
762
+ },
763
+ sys_hub_flow_logic_instance_v2: {
764
+ via: 'flow',
765
+ descendant: true,
766
+ },
767
+ sys_hub_sub_flow_instance_v2: {
768
+ via: 'flow',
769
+ descendant: true,
770
+ },
771
+ };
772
+ /**
773
+ * Checks if children array contains datapill references (e.g., "{{trigger.field}}")
774
+ */
775
+ function childrenContainDatapills(children) {
776
+ if (!Array.isArray(children)) {
777
+ return false;
778
+ }
779
+ for (const child of children) {
780
+ // Check if value contains datapill markers
781
+ if ((0, complex_object_resolver_1.isDataPill)(child.value)) {
782
+ return true;
783
+ }
784
+ // Recursively check nested children
785
+ if (child.children && Array.isArray(child.children) && childrenContainDatapills(child.children)) {
786
+ return true;
787
+ }
788
+ }
789
+ return false;
790
+ }
791
+ /**
792
+ * Builds the parameter object for a variable with schema information
793
+ */
794
+ function buildParameterObject(varName, _children, serviceNowValue, logger) {
795
+ // Parse the ServiceNow formatted value to extract schema
796
+ try {
797
+ const parsed = JSON.parse(serviceNowValue);
798
+ if (!parsed.complexObjectSchema) {
799
+ return {};
800
+ }
801
+ // Extract the schema key (e.g., "FlowDesigner:FDxxx")
802
+ const schemaKeys = Object.keys(parsed.complexObjectSchema);
803
+ const mainSchemaKey = schemaKeys.find((key) => key.startsWith('FlowDesigner:') && !key.includes('.$'));
804
+ if (!mainSchemaKey) {
805
+ return {};
806
+ }
807
+ const schema = parsed.complexObjectSchema[mainSchemaKey];
808
+ const typeFacetsKey = `${mainSchemaKey}.$type_facets`;
809
+ const typeFacets = parsed.complexObjectSchema[typeFacetsKey]?.SimpleMapFacet;
810
+ if (!typeFacets) {
811
+ return {};
812
+ }
813
+ const typeFacetsObj = JSON.parse(typeFacets);
814
+ // Build parameter object
815
+ const parameter = {
816
+ children: [],
817
+ type_label: typeFacetsObj.uiTypeLabel || 'Object',
818
+ id: typeFacetsObj.id || '',
819
+ label: typeFacetsObj.label || varName,
820
+ name: varName,
821
+ type: typeFacetsObj.uiType || 'object',
822
+ order: parseInt(typeFacetsObj.order || '0', 10),
823
+ extended: false,
824
+ mandatory: typeFacetsObj.mandatory === 'true',
825
+ readOnly: typeFacetsObj.read_only === 'true',
826
+ hint: typeFacetsObj.hint || '',
827
+ maxsize: parseInt(typeFacetsObj.max_length || '0', 10),
828
+ reference: '',
829
+ reference_display: '',
830
+ choiceOption: typeFacetsObj.choiceOption || '',
831
+ table: '',
832
+ columnName: '',
833
+ defaultValue: typeFacetsObj.default_value || '',
834
+ use_dependent: false,
835
+ fShowReferenceFinder: false,
836
+ local: false,
837
+ attributes: {},
838
+ ref_qual: '',
839
+ dependent_on: '',
840
+ };
841
+ // Copy attributes
842
+ for (const [key, value] of Object.entries(typeFacetsObj)) {
843
+ if (![
844
+ 'label',
845
+ 'type',
846
+ 'order',
847
+ 'mandatory',
848
+ 'read_only',
849
+ 'hint',
850
+ 'max_length',
851
+ 'choiceOption',
852
+ 'default_value',
853
+ ].includes(key)) {
854
+ parameter.attributes[key] = value;
855
+ }
856
+ }
857
+ // Build children array from schema
858
+ for (const [fieldName, _fieldType] of Object.entries(schema)) {
859
+ if (fieldName.includes('.$') || fieldName === 'name$' || fieldName === COMPLEX_OBJECT_COLLECTION_FIELD) {
860
+ continue;
861
+ }
862
+ const fieldFacetsKey = `${fieldName}.$field_facets`;
863
+ const fieldFacets = schema[fieldFacetsKey]?.SimpleMapFacet;
864
+ if (!fieldFacets) {
865
+ continue;
866
+ }
867
+ const fieldFacetsObj = JSON.parse(fieldFacets);
868
+ // Build fieldFacetMap with mapped datapills
869
+ const fieldFacetMap = {
870
+ choiceOption: fieldFacetsObj.choiceOption || '',
871
+ uiTypeLabel: fieldFacetsObj.uiTypeLabel || '',
872
+ };
873
+ // Check if this field has a datapill mapping
874
+ if (fieldFacetsObj.mapped) {
875
+ fieldFacetMap.mapped = fieldFacetsObj.mapped;
876
+ }
877
+ const childParam = {
878
+ fieldFacetMap,
879
+ value: fieldFacetsObj.default_value || '',
880
+ scriptActive: false,
881
+ script: {},
882
+ children: [],
883
+ uiDisplayType: fieldFacetsObj.uiType || '',
884
+ type_label: fieldFacetsObj.uiTypeLabel || '',
885
+ id: '',
886
+ label: fieldFacetsObj.label || fieldName,
887
+ name: fieldName,
888
+ type: fieldFacetsObj.uiType || 'string',
889
+ order: parseInt(fieldFacetsObj.order || '0', 10),
890
+ extended: false,
891
+ mandatory: fieldFacetsObj.mandatory === 'true',
892
+ readOnly: fieldFacetsObj.read_only === 'true',
893
+ hint: fieldFacetsObj.hint || '',
894
+ maxsize: parseInt(fieldFacetsObj.max_length || '0', 10),
895
+ reference: '',
896
+ reference_display: '',
897
+ choiceOption: fieldFacetsObj.choiceOption || '',
898
+ table: '',
899
+ columnName: '',
900
+ defaultValue: fieldFacetsObj.default_value || '',
901
+ defaultDisplayValue: '',
902
+ use_dependent: false,
903
+ fShowReferenceFinder: false,
904
+ local: false,
905
+ attributes: {},
906
+ ref_qual: '',
907
+ dependent_on: '',
908
+ };
909
+ parameter.children.push(childParam);
910
+ }
911
+ return parameter;
912
+ }
913
+ catch (e) {
914
+ logger.error(`Error building parameter object for variable ${varName}: ${e}`);
915
+ return {};
916
+ }
917
+ }
918
+ /**
919
+ * Enriches children array with parameter metadata from ServiceNow formatted value
920
+ */
921
+ function enrichChildrenWithParameters(children, serviceNowValue, logger, clearValues = false) {
922
+ if (!children || !Array.isArray(children)) {
923
+ return children;
924
+ }
925
+ try {
926
+ const parsed = JSON.parse(serviceNowValue);
927
+ if (!parsed.complexObjectSchema) {
928
+ return children;
929
+ }
930
+ // Extract the schema
931
+ const schemaKeys = Object.keys(parsed.complexObjectSchema);
932
+ const mainSchemaKey = schemaKeys.find((key) => key.startsWith('FlowDesigner:') && !key.includes('.$'));
933
+ if (!mainSchemaKey) {
934
+ return children;
935
+ }
936
+ const schema = parsed.complexObjectSchema[mainSchemaKey];
937
+ return children.map((child) => {
938
+ const fieldFacetsKey = `${child.name}.$field_facets`;
939
+ const fieldFacets = schema[fieldFacetsKey]?.SimpleMapFacet;
940
+ if (!fieldFacets) {
941
+ return child;
942
+ }
943
+ const fieldFacetsObj = JSON.parse(fieldFacets);
944
+ const parameter = {
945
+ children: [],
946
+ uiDisplayType: fieldFacetsObj.uiType || '',
947
+ type_label: fieldFacetsObj.uiTypeLabel || '',
948
+ id: '',
949
+ label: fieldFacetsObj.label || child.name,
950
+ name: child.name,
951
+ type: fieldFacetsObj.uiType || 'string',
952
+ order: parseInt(fieldFacetsObj.order || '0', 10),
953
+ extended: false,
954
+ mandatory: fieldFacetsObj.mandatory === 'true',
955
+ readOnly: fieldFacetsObj.read_only === 'true',
956
+ hint: fieldFacetsObj.hint || '',
957
+ maxsize: parseInt(fieldFacetsObj.max_length || '0', 10),
958
+ reference: '',
959
+ reference_display: '',
960
+ choiceOption: fieldFacetsObj.choiceOption || '',
961
+ table: '',
962
+ columnName: '',
963
+ defaultValue: fieldFacetsObj.default_value || '',
964
+ defaultDisplayValue: '',
965
+ use_dependent: false,
966
+ fShowReferenceFinder: false,
967
+ local: false,
968
+ attributes: {},
969
+ ref_qual: '',
970
+ dependent_on: '',
971
+ };
972
+ return {
973
+ ...child,
974
+ id: '',
975
+ value: clearValues ? '' : child.value,
976
+ displayValue: clearValues ? '' : child.displayValue || '',
977
+ parameter,
978
+ scriptActive: false,
979
+ script: {},
980
+ };
981
+ });
982
+ }
983
+ catch (e) {
984
+ logger.error('Error enriching children with parameters:', e);
985
+ return children;
986
+ }
987
+ }
988
+ /**
989
+ * Post-processes setFlowVariables values to apply ServiceNow complex object serialization.
990
+ * For variables with FlowObject/FlowArray types, replaces plain JSON with the proper
991
+ * ServiceNow format including $cv wrappers, schema, version, and serializationFormat.
992
+ *
993
+ * @param valuesJSON - The values array from the flow logic instance
994
+ * @param flowDefinitionRecord - The flow definition record containing variable definitions
995
+ * @returns Updated values array with complex objects properly serialized
996
+ */
997
+ function postProcessSetFlowVariables(valuesJSON, flowDefinitionRecord, logger) {
998
+ if (!valuesJSON) {
999
+ return valuesJSON;
1000
+ }
1001
+ // Helper function to process a single variable entry
1002
+ const processVariable = (variable) => {
1003
+ // Check if this variable has children array
1004
+ // Note: Empty arrays should still be processed to generate ServiceNow complex object format
1005
+ if (!variable.children || !Array.isArray(variable.children)) {
1006
+ return variable;
1007
+ }
1008
+ // For variables with empty children, check if the value is an empty array that needs processing
1009
+ const hasEmptyArrayValue = variable.children.length === 0 && variable.value === '[]';
1010
+ if (variable.children.length === 0 && !hasEmptyArrayValue) {
1011
+ return variable;
1012
+ }
1013
+ // Check if children contain datapills
1014
+ const hasDatapills = childrenContainDatapills(variable.children);
1015
+ // If value is empty but has datapills, we need to get the ServiceNow format from variables array
1016
+ if (!variable.value && hasDatapills) {
1017
+ // Find the corresponding entry in the variables array
1018
+ const correspondingVar = valuesJSON.variables?.find((v) => v.name === variable.name);
1019
+ if (correspondingVar?.value) {
1020
+ // Build parameter using the variables array value (which has ServiceNow format)
1021
+ const parameter = buildParameterObject(variable.name, variable.children, correspondingVar.value, logger);
1022
+ // Enrich children with parameter objects
1023
+ const enrichedChildren = enrichChildrenWithParameters(variable.children, correspondingVar.value, logger);
1024
+ return {
1025
+ ...variable,
1026
+ children: enrichedChildren,
1027
+ parameter,
1028
+ };
1029
+ }
1030
+ return variable;
1031
+ }
1032
+ // If no value and no datapills, skip processing
1033
+ if (!variable.value) {
1034
+ return variable;
1035
+ }
1036
+ // Try to parse the value to see if it's plain JSON (not already in ServiceNow format)
1037
+ let parsedValue;
1038
+ try {
1039
+ parsedValue = JSON.parse(variable.value);
1040
+ }
1041
+ catch (_e) {
1042
+ // If it's not valid JSON, leave it as is
1043
+ logger.error('Error parsing value:', variable.value);
1044
+ return variable;
1045
+ }
1046
+ // Check if parsedValue is null or not an object
1047
+ if (!parsedValue || typeof parsedValue !== 'object') {
1048
+ return variable;
1049
+ }
1050
+ // Check if it's already in ServiceNow format (has version, complexObjectSchema, etc.)
1051
+ if ('version' in parsedValue || 'complexObjectSchema' in parsedValue || 'serializationFormat' in parsedValue) {
1052
+ // Already in ServiceNow format, check if we need to add parameter
1053
+ if (hasDatapills) {
1054
+ const parameter = buildParameterObject(variable.name, variable.children, variable.value, logger);
1055
+ // Enrich children with parameter objects
1056
+ const enrichedChildren = enrichChildrenWithParameters(variable.children, variable.value, logger);
1057
+ return {
1058
+ ...variable,
1059
+ children: enrichedChildren,
1060
+ parameter,
1061
+ };
1062
+ }
1063
+ return variable;
1064
+ }
1065
+ // Check if it's a plain object or array (potential FlowObject/FlowArray)
1066
+ const isObject = parsedValue && typeof parsedValue === 'object' && !Array.isArray(parsedValue);
1067
+ const isArray = Array.isArray(parsedValue);
1068
+ if (!isObject && !isArray) {
1069
+ return variable;
1070
+ }
1071
+ // Use resolveComplexInput to get the proper ServiceNow format
1072
+ const resolved = (0, complex_object_resolver_2.resolveComplexInput)(variable.name, parsedValue, flowDefinitionRecord, 'sys_hub_flow_variable');
1073
+ if (resolved?.value && typeof resolved.value === 'string' && resolved.value !== variable.value) {
1074
+ // Use children from resolveComplexInput if available (has correct child_name), otherwise use existing
1075
+ const childrenToUse = resolved.children || variable.children;
1076
+ // Build parameter object if children contain datapills
1077
+ const parameter = hasDatapills
1078
+ ? buildParameterObject(variable.name, childrenToUse, resolved.value, logger)
1079
+ : {};
1080
+ // Enrich children with parameter objects
1081
+ const enrichedChildren = enrichChildrenWithParameters(childrenToUse, resolved.value, logger);
1082
+ return {
1083
+ ...variable,
1084
+ value: resolved.value,
1085
+ displayValue: resolved.value,
1086
+ children: enrichedChildren,
1087
+ parameter,
1088
+ };
1089
+ }
1090
+ return variable;
1091
+ };
1092
+ // Process variables array first
1093
+ const updatedVariables = valuesJSON.variables && Array.isArray(valuesJSON.variables)
1094
+ ? valuesJSON.variables.map((v) => processVariable(v))
1095
+ : valuesJSON.variables;
1096
+ // Create intermediate object with updated variables for inputs processing
1097
+ const intermediateJSON = {
1098
+ ...valuesJSON,
1099
+ variables: updatedVariables,
1100
+ };
1101
+ // Then process inputs array, which can now reference the updated variables
1102
+ const updatedInputs = intermediateJSON.inputs && Array.isArray(intermediateJSON.inputs)
1103
+ ? intermediateJSON.inputs.map((v) => {
1104
+ // Update the closure to use intermediateJSON instead of valuesJSON
1105
+ const hasDatapills = v.children && Array.isArray(v.children) && childrenContainDatapills(v.children);
1106
+ if (!v.value && hasDatapills && v.children) {
1107
+ const correspondingVar = intermediateJSON.variables?.find((variable) => variable.name === v.name);
1108
+ if (correspondingVar?.value) {
1109
+ const parameter = buildParameterObject(v.name, v.children, correspondingVar.value, logger);
1110
+ // Enrich children with parameter objects, clearing values for inputs array
1111
+ const enrichedChildren = enrichChildrenWithParameters(v.children, correspondingVar.value, logger, true);
1112
+ return { ...v, children: enrichedChildren, parameter };
1113
+ }
1114
+ }
1115
+ return processVariable(v);
1116
+ })
1117
+ : intermediateJSON.inputs;
1118
+ return {
1119
+ ...intermediateJSON,
1120
+ inputs: updatedInputs,
1121
+ };
1122
+ }
1123
+ /**
1124
+ * Post-processes assignSubflowOutputs to apply complex object serialization for FlowObject and FlowArray outputs.
1125
+ * This is necessary because assignSubflowOutputs generates plain JSON for FlowObject/FlowArray values,
1126
+ * but ServiceNow requires them to be in the complex object format with schemas.
1127
+ *
1128
+ * Similar to postProcessSetFlowVariables, but processes outputsToAssign array instead of variables array.
1129
+ *
1130
+ * @param valuesJSON - The values JSON containing outputsToAssign array
1131
+ * @param subflowDefinitionRecord - The subflow definition record for schema lookup
1132
+ * @returns Updated valuesJSON with properly formatted complex objects
1133
+ */
1134
+ function postProcessAssignSubflowOutputs(valuesJSON, subflowDefinitionRecord, logger) {
1135
+ if (!valuesJSON || !valuesJSON.outputsToAssign || !Array.isArray(valuesJSON.outputsToAssign)) {
1136
+ return valuesJSON;
1137
+ }
1138
+ // Helper function to process a single output entry
1139
+ const processOutput = (output) => {
1140
+ // Check if this output has children array
1141
+ // Note: Empty arrays should still be processed to generate ServiceNow complex object format
1142
+ if (!output.children || !Array.isArray(output.children)) {
1143
+ return output;
1144
+ }
1145
+ // For outputs with empty children, check if the value is an empty array that needs processing
1146
+ const hasEmptyArrayValue = output.children.length === 0 && output.value === '[]';
1147
+ if (output.children.length === 0 && !hasEmptyArrayValue) {
1148
+ return output;
1149
+ }
1150
+ // Check if children contain datapills
1151
+ const hasDatapills = childrenContainDatapills(output.children);
1152
+ // If no value and no datapills, skip processing
1153
+ if (!output.value) {
1154
+ return output;
1155
+ }
1156
+ // Try to parse the value to see if it's plain JSON (not already in ServiceNow format)
1157
+ let parsedValue;
1158
+ try {
1159
+ parsedValue = JSON.parse(output.value);
1160
+ }
1161
+ catch (_e) {
1162
+ // If it's not valid JSON, leave it as is
1163
+ logger.error('Error parsing value:', output.value);
1164
+ return output;
1165
+ }
1166
+ // Check if parsedValue is null or not an object
1167
+ if (!parsedValue || typeof parsedValue !== 'object') {
1168
+ return output;
1169
+ }
1170
+ // Check if it's already in ServiceNow format (has version, complexObjectSchema, etc.)
1171
+ if ('version' in parsedValue || 'complexObjectSchema' in parsedValue || 'serializationFormat' in parsedValue) {
1172
+ // Already in ServiceNow format, check if we need to add parameter
1173
+ if (hasDatapills) {
1174
+ const parameter = buildParameterObject(output.name, output.children, output.value, logger);
1175
+ // Enrich children with parameter objects
1176
+ const enrichedChildren = enrichChildrenWithParameters(output.children, output.value, logger);
1177
+ return {
1178
+ ...output,
1179
+ children: enrichedChildren,
1180
+ parameter,
1181
+ };
1182
+ }
1183
+ return output;
1184
+ }
1185
+ // Check if it's a plain object or array (potential FlowObject/FlowArray)
1186
+ const isObject = parsedValue && typeof parsedValue === 'object' && !Array.isArray(parsedValue);
1187
+ const isArray = Array.isArray(parsedValue);
1188
+ if (!isObject && !isArray) {
1189
+ // Not a complex type, leave as is
1190
+ return output;
1191
+ }
1192
+ // Use resolveComplexInput to get the proper ServiceNow format
1193
+ // For subflow outputs, we look in sys_hub_flow_output table (same as flow outputs)
1194
+ const resolved = (0, complex_object_resolver_2.resolveComplexInput)(output.name, parsedValue, subflowDefinitionRecord, 'sys_hub_flow_output');
1195
+ if (resolved?.value && typeof resolved.value === 'string' && resolved.value !== output.value) {
1196
+ // Use children from resolveComplexInput if available (has correct child_name), otherwise use existing
1197
+ const childrenToUse = resolved.children || output.children;
1198
+ // Build parameter object if children contain datapills
1199
+ const parameter = hasDatapills
1200
+ ? buildParameterObject(output.name, childrenToUse, resolved.value, logger)
1201
+ : {};
1202
+ // Enrich children with parameter objects
1203
+ let enrichedChildren = enrichChildrenWithParameters(childrenToUse, resolved.value, logger);
1204
+ // For assignSubflowOutputs, prepend parent output name to child names (dotted format)
1205
+ // e.g., "tag" becomes "tags.tag"
1206
+ enrichedChildren = enrichedChildren.map((child) => ({
1207
+ ...child,
1208
+ name: `${output.name}.${child.name}`,
1209
+ }));
1210
+ return {
1211
+ ...output,
1212
+ value: resolved.value,
1213
+ displayValue: resolved.value,
1214
+ children: enrichedChildren,
1215
+ parameter,
1216
+ };
1217
+ }
1218
+ return output;
1219
+ };
1220
+ // Process outputsToAssign array
1221
+ const updatedOutputs = valuesJSON.outputsToAssign.map((output) => processOutput(output));
1222
+ return {
1223
+ ...valuesJSON,
1224
+ outputsToAssign: updatedOutputs,
1225
+ };
1226
+ }
1227
+ exports.FlowDefinitionPlugin = sdk_build_core_1.Plugin.create({
1228
+ name: 'FlowDefinitionPlugin',
1229
+ records: {
1230
+ sys_hub_flow: {
1231
+ relationships: {
1232
+ ...commonFlowRelationships,
1233
+ ...commonInstanceV2Relationships,
1234
+ sys_flow_record_trigger: {
1235
+ via: 'remote_trigger_id',
1236
+ inverse: true,
1237
+ descendant: true,
1238
+ },
1239
+ sys_trigger_runner_mapping: {
1240
+ via: 'identifier',
1241
+ descendant: true,
1242
+ },
1243
+ sys_flow_trigger_plan: {
1244
+ via: 'plan_id',
1245
+ descendant: true,
1246
+ },
1247
+ sys_flow_timer_trigger: {
1248
+ via: 'remote_trigger_id',
1249
+ inverse: true,
1250
+ descendant: true,
1251
+ relationships: {
1252
+ sys_flow_trigger_auto_script: {
1253
+ via: 'trigger',
1254
+ descendant: true,
1255
+ },
1256
+ },
1257
+ },
1258
+ sys_variable_value: {
1259
+ via: 'document_key',
1260
+ descendant: true,
1261
+ },
1262
+ sys_translated_text: {
1263
+ via: 'documentkey',
1264
+ descendant: true,
1265
+ },
1266
+ sys_hub_flow_snapshot: {
1267
+ via: 'parent_flow',
1268
+ descendant: true,
1269
+ relationships: {
1270
+ ...commonFlowRelationships,
1271
+ ...commonInstanceV2Relationships,
1272
+ },
1273
+ },
1274
+ sys_flow_subflow_plan: {
1275
+ via: 'plan_id',
1276
+ descendant: true,
1277
+ },
1278
+ sys_hub_flow_variable: {
1279
+ via: 'model',
1280
+ descendant: true,
1281
+ },
1282
+ sys_hub_flow_stage: {
1283
+ via: 'flow',
1284
+ descendant: true,
1285
+ },
1286
+ },
1287
+ getUpdateName(record) {
1288
+ return { success: true, value: `${record.getTable()}_${record.getId().getValue()}` };
1289
+ },
1290
+ toFile(record, { config, database }) {
1291
+ return (0, flow_to_xml_1.generateXML)(record, { config, database });
1292
+ },
1293
+ async diff(existing, incoming, descendants, context) {
1294
+ return (0, sdk_build_core_1.deleteMultipleDiff)(existing, incoming, descendants, context);
1295
+ },
1296
+ async toShape(record, { descendants, diagnostics, transform, database, logger }) {
1297
+ let type = record.get('type')?.getValue();
1298
+ if (!type) {
1299
+ logger.warn(`sys_hub_flow record has no type specified, defaulting to 'flow'`);
1300
+ type = 'flow';
1301
+ }
1302
+ else if (type !== 'flow' && type !== 'subflow') {
1303
+ logger.error(`Skipping sys_hub_flow record: expected type 'flow' or 'subflow', but received '${type}'`);
1304
+ return { success: false };
1305
+ }
1306
+ const isSubflow = type === 'subflow';
1307
+ const isFlow = type === 'flow';
1308
+ const inputs = (0, flow_io_to_record_1.buildVariableShapes)(descendants.query('sys_hub_flow_input'), descendants, logger);
1309
+ const outputs = (0, flow_io_to_record_1.buildVariableShapes)(descendants.query('sys_hub_flow_output'), descendants, logger);
1310
+ //If Flow has unsupported datatypes for inputs/outputs, fallback to Record() API
1311
+ if (inputs === undefined || outputs === undefined) {
1312
+ return { success: false };
1313
+ }
1314
+ const flowVariables = (0, flow_io_to_record_1.buildVariableShapes)(descendants.query('sys_hub_flow_variable'), descendants);
1315
+ //Check if flow has unsupported descendants are present
1316
+ if ((0, utils_1.checkForUnsupportedFlowDescendants)(descendants, record, logger)) {
1317
+ return { success: false };
1318
+ }
1319
+ const trigger = descendants.query('sys_hub_trigger_instance_v2')[0]; // There will be only 1 trigger per flow
1320
+ let triggerShape = new sdk_build_core_1.UndefinedShape({
1321
+ source: record.getSource(),
1322
+ });
1323
+ if (isFlow) {
1324
+ if (trigger) {
1325
+ const triggerShapeResult = await transform.recordToShape(trigger, database, flow_trigger_instance_plugin_1.TriggerInstancePlugin);
1326
+ if (triggerShapeResult.success) {
1327
+ triggerShape = triggerShapeResult.value.as(sdk_build_core_1.CallExpressionShape);
1328
+ }
1329
+ else {
1330
+ return { success: false };
1331
+ }
1332
+ }
1333
+ }
1334
+ const actionInstances = descendants.query('sys_hub_action_instance_v2', {
1335
+ flow: record.getId().getValue(), // This is to skip snapshot records
1336
+ });
1337
+ const flowLogicInstance = descendants.query('sys_hub_flow_logic_instance_v2', {
1338
+ flow: record.getId().getValue(),
1339
+ });
1340
+ const subflowInstance = descendants.query('sys_hub_sub_flow_instance_v2', {
1341
+ flow: record.getId().getValue(),
1342
+ });
1343
+ const order = (rec) => Number(rec.get('order')?.getValue());
1344
+ // Build UUID map from ALL instances (actions, subflows, and flow logic)
1345
+ const allInstances = [...actionInstances, ...subflowInstance, ...flowLogicInstance];
1346
+ const recordToShapeMap = new Map();
1347
+ const allInstanceShapes = [];
1348
+ for (const instance of allInstances) {
1349
+ const instanceShapeResult = await transform.recordToShape(instance, database, flow_instance_plugin_1.FlowInstancePlugin, flow_logic_plugin_1.FlowLogicPlugin);
1350
+ if (instanceShapeResult.success) {
1351
+ const shape = instanceShapeResult.value;
1352
+ recordToShapeMap.set(instance, shape);
1353
+ allInstanceShapes.push(shape);
1354
+ }
1355
+ }
1356
+ // Build UUID map from all transformed shapes and their records
1357
+ // Use recordToShapeMap to access ui_id from records (datapills reference ui_id, not $id)
1358
+ const uuidToIdentifierMap = (0, datapill_transformer_1.buildUuidToIdentifierMap)(recordToShapeMap);
1359
+ // For the flow body, only use top-level instances (those without parent_ui_id)
1360
+ const topLevelInstances = allInstances
1361
+ .filter((instance) => !instance.get('parent_ui_id').isDefined() || instance.get('parent_ui_id').getValue() === '')
1362
+ .sort((a, b) => order(a) - order(b));
1363
+ const instanceShapes = [];
1364
+ for (const instance of topLevelInstances) {
1365
+ const shape = recordToShapeMap.get(instance);
1366
+ if (!shape) {
1367
+ logger.error(`Failed to find shape for instance ${instance.getId().getValue()}`);
1368
+ return { success: false };
1369
+ }
1370
+ instanceShapes.push(shape);
1371
+ }
1372
+ // Transform datapill expressions in instance props
1373
+ // This section handles TWO types of datapills:
1374
+ // 1. UUID-based pills: {{uuid.property}} → references to previous action/subflow instances (e.g., {{f56a03c1-18f6-4f7b-9c61-0d4ff472b334.name}} → actionInstance_1.name)
1375
+ // 2. Semantic pills: {{trigger.property}}, {{flow_variable.name}} → references to flow parameters (e.g., {{trigger.table_name}} → params.trigger.table_name)
1376
+ // Extract parameter name from the topmost ArrowFunction
1377
+ // This allows us to use the actual parameter name instead of hardcoding "params"
1378
+ let paramName = flow_plugin_constants_1.DEFAULT_PARAM_NAME; // Default fallback
1379
+ const firstInstance = instanceShapes[0];
1380
+ if (firstInstance) {
1381
+ paramName = getArrowFunctionParamName(firstInstance) || flow_plugin_constants_1.DEFAULT_PARAM_NAME;
1382
+ }
1383
+ // Process all instances (Action, Subflow, and Flow Logic) recursively
1384
+ // This handles datapill transformation for all instance types and their nested children
1385
+ instanceShapes.forEach((instanceShape, index) => {
1386
+ const result = (0, datapill_transformer_1.processInstanceForDatapills)(instanceShape, uuidToIdentifierMap, record, diagnostics, paramName, logger, processShapeForDatapills, cleanupConfigShape);
1387
+ // Only update if transformations occurred
1388
+ if (result.propsChanged) {
1389
+ instanceShapes[index] = result.shape;
1390
+ }
1391
+ });
1392
+ const flowBody = new arrow_function_plugin_1.ArrowFunctionShape({
1393
+ source: record,
1394
+ parameters: [new sdk_build_core_1.IdentifierShape({ source: record, name: paramName })],
1395
+ statements: instanceShapes,
1396
+ });
1397
+ // Create the CallExpressionShape for both flow and subflow
1398
+ const callExpression = new sdk_build_core_1.CallExpressionShape({
1399
+ source: record,
1400
+ callee: isSubflow ? flow_constants_1.SUBFLOW_API_NAME : flow_constants_1.FLOW_API_NAME,
1401
+ args: [
1402
+ record.transform(({ $ }) => ({
1403
+ $id: $.val(now_id_plugin_1.NowIdShape.from(record)),
1404
+ name: $,
1405
+ description: $.def(flow_plugin_constants_1.EMPTY_STRING),
1406
+ protection: $.from('sys_policy').def(flow_plugin_constants_1.EMPTY_STRING),
1407
+ runAs: $.from('run_as').def(flow_plugin_constants_1.RUN_AS_DEFAULT),
1408
+ runWithRoles: $.from('run_with_roles')
1409
+ .map((r) => {
1410
+ const roles = r.ifString()?.getValue() ?? '';
1411
+ return roles
1412
+ .split(',')
1413
+ .map((role) => role.trim())
1414
+ .filter((role) => role);
1415
+ })
1416
+ .def([]),
1417
+ flowPriority: $.from('flow_priority')
1418
+ .map((p) => p.ifString()?.getValue() || flow_plugin_constants_1.FLOW_PRIORITY_DEFAULT)
1419
+ .def(flow_plugin_constants_1.FLOW_PRIORITY_DEFAULT),
1420
+ ...(isSubflow
1421
+ ? {
1422
+ annotation: $.def(flow_plugin_constants_1.EMPTY_STRING),
1423
+ category: $.def(flow_plugin_constants_1.EMPTY_STRING),
1424
+ access: $.def(flow_plugin_constants_1.ACCESS_DEFAULT),
1425
+ inputs: $.val(inputs).def({}),
1426
+ outputs: $.val(outputs).def({}),
1427
+ }
1428
+ : {}),
1429
+ flowVariables: $.val(flowVariables).def({}),
1430
+ })),
1431
+ ...(isFlow ? [triggerShape, flowBody] : [flowBody]),
1432
+ ],
1433
+ });
1434
+ // For subflows, wrap in VariableStatementShape with isExported true
1435
+ // For flows, return the CallExpressionShape directly
1436
+ if (isSubflow) {
1437
+ // Try to get the existing identifier from the record source, fallback to slugified name
1438
+ const flowName = (0, utils_1.getIdentifierFromRecord)(record) ??
1439
+ (0, flow_constants_1.slugifyString)(String(record.get('internal_name')?.getValue() || record.get('name')?.getValue()));
1440
+ return {
1441
+ success: true,
1442
+ value: new sdk_build_core_1.VariableStatementShape({
1443
+ source: record,
1444
+ variableName: flowName,
1445
+ initializer: callExpression,
1446
+ isExported: true,
1447
+ }),
1448
+ };
1449
+ }
1450
+ else {
1451
+ return {
1452
+ success: true,
1453
+ value: callExpression,
1454
+ };
1455
+ }
1456
+ },
1457
+ },
1458
+ sys_hub_flow_input: {
1459
+ coalesce: ['model', 'element'],
1460
+ },
1461
+ sys_hub_flow_output: {
1462
+ coalesce: ['model', 'element'],
1463
+ },
1464
+ sys_complex_object: {
1465
+ coalesce: ['name'],
1466
+ },
1467
+ sys_hub_flow_variable: {
1468
+ coalesce: ['model', 'element'],
1469
+ },
1470
+ sys_hub_flow_stage: {
1471
+ coalesce: ['flow', 'value'],
1472
+ },
1473
+ sys_variable_value: {
1474
+ coalesce: ['document_key', 'variable'],
1475
+ },
1476
+ },
1477
+ shapes: [
1478
+ {
1479
+ shape: sdk_build_core_1.CallExpressionShape,
1480
+ fileTypes: ['fluent'],
1481
+ async toRecord(callExpression, { factory, diagnostics, transform, logger }) {
1482
+ const isFlow = callExpression.getCallee() === flow_constants_1.FLOW_API_NAME;
1483
+ const isSubflow = callExpression.getCallee() === flow_constants_1.SUBFLOW_API_NAME;
1484
+ if (!isFlow && !isSubflow) {
1485
+ return { success: false };
1486
+ }
1487
+ let flowConfiguration, triggerInstance, flowBody;
1488
+ const relatedRecords = [];
1489
+ if (isFlow) {
1490
+ flowConfiguration = callExpression.getArgument(0).asObject();
1491
+ const triggerInstanceCE = callExpression.getArgument(1)?.if(sdk_build_core_1.UndefinedShape)
1492
+ ? undefined
1493
+ : callExpression.getArgument(1)?.as(sdk_build_core_1.CallExpressionShape);
1494
+ const triggerInstanceRecord = triggerInstanceCE
1495
+ ? await transform.toRecord(triggerInstanceCE, flow_trigger_instance_plugin_1.TriggerInstancePlugin)
1496
+ : undefined;
1497
+ triggerInstance = triggerInstanceRecord?.success ? triggerInstanceRecord.value : undefined;
1498
+ flowBody = !callExpression.getArgument(2)?.if(sdk_build_core_1.UndefinedShape)
1499
+ ? callExpression.getArgument(2)?.as(arrow_function_plugin_1.ArrowFunctionShape)
1500
+ : undefined;
1501
+ }
1502
+ else {
1503
+ flowConfiguration = callExpression.getArgument(0).asObject();
1504
+ flowBody = !callExpression.getArgument(1)?.if(sdk_build_core_1.UndefinedShape)
1505
+ ? callExpression.getArgument(1)?.as(arrow_function_plugin_1.ArrowFunctionShape)
1506
+ : undefined;
1507
+ }
1508
+ const roles = flowConfiguration.get('runWithRoles').ifArray()?.getElements() ?? [];
1509
+ const flowDefinitionRecord = await factory.createRecord({
1510
+ source: callExpression,
1511
+ table: 'sys_hub_flow',
1512
+ explicitId: flowConfiguration.get('$id'),
1513
+ properties: flowConfiguration.transform(({ $ }) => ({
1514
+ name: $,
1515
+ internal_name: $.from('name').map((n) => (0, flow_constants_1.slugifyString)(n.getValue())),
1516
+ annotation: $.def(flow_plugin_constants_1.EMPTY_STRING),
1517
+ description: $.def(flow_plugin_constants_1.EMPTY_STRING),
1518
+ access: $.def(flow_plugin_constants_1.ACCESS_DEFAULT),
1519
+ category: $.def(flow_plugin_constants_1.EMPTY_STRING),
1520
+ sys_policy: $.from('protection').def(flow_plugin_constants_1.EMPTY_STRING),
1521
+ run_as: $.from('runAs').def(flow_plugin_constants_1.RUN_AS_DEFAULT),
1522
+ generation_source: $.def(flow_plugin_constants_1.GENERATION_SOURCE),
1523
+ show_draft_actions: $.def(flow_plugin_constants_1.BOOLEAN_FALSE_STRING),
1524
+ flow_priority: $.from('flowPriority').def(flow_plugin_constants_1.FLOW_PRIORITY_DEFAULT),
1525
+ run_with_roles: $.val(Array.from(new Set(roles.map((r) => r.ifRecord()?.getId().getValue() ?? r.getValue()))).join(',')),
1526
+ active: $.val(false),
1527
+ status: $.val(flow_plugin_constants_1.FLOW_STATUS_DRAFT),
1528
+ type: isFlow ? $.def(flow_plugin_constants_1.FLOW_TYPE_FLOW) : $.def(flow_plugin_constants_1.FLOW_TYPE_SUBFLOW),
1529
+ version: $.def(flow_plugin_constants_1.FLOW_VERSION),
1530
+ label_cache: $.val('[]'),
1531
+ })),
1532
+ });
1533
+ if (isFlow && triggerInstance) {
1534
+ // Push updated trigger instance record
1535
+ relatedRecords.push(triggerInstance.merge({
1536
+ flow: flowDefinitionRecord.getId().getValue(),
1537
+ }));
1538
+ }
1539
+ // ------------------------------------------------------------
1540
+ // Handle FlowVariables() argument (flow-level variables)
1541
+ // Each variable becomes a separate sys_hub_flow_variable record
1542
+ // ------------------------------------------------------------
1543
+ if (flowConfiguration.has('flowVariables')) {
1544
+ const variablesConfig = flowConfiguration.get('flowVariables').asObject();
1545
+ // --------------------------------------------------------------------
1546
+ // Validate each variable is created using a supported FlowValueType
1547
+ // --------------------------------------------------------------------
1548
+ variablesConfig.entries().forEach(([key, value]) => {
1549
+ if (!value.if(sdk_build_core_1.CallExpressionShape)) {
1550
+ diagnostics.error(value.getOriginalNode(), `flowVariables.${key} is not a valid variable expression.`);
1551
+ return;
1552
+ }
1553
+ // Use the shared validation function
1554
+ (0, utils_1.validateFlowVariableCall)(value.as(sdk_build_core_1.CallExpressionShape), `flowVariables.${key}`, diagnostics);
1555
+ });
1556
+ const flowVarRecords = await (0, flow_variable_processor_1.processFlowVariables)(variablesConfig, flowDefinitionRecord, factory, diagnostics);
1557
+ relatedRecords.push(...flowVarRecords);
1558
+ }
1559
+ if (isSubflow) {
1560
+ // Process subflow inputs and outputs
1561
+ const inputsConfig = flowConfiguration.get('inputs').ifObject()?.asObject();
1562
+ const inputRecords = await (0, flow_variable_processor_1.processFlowInputs)(inputsConfig, flowDefinitionRecord, factory, diagnostics);
1563
+ relatedRecords.push(...inputRecords);
1564
+ const outputsConfig = flowConfiguration.get('outputs').ifObject()?.asObject();
1565
+ const outputRecords = await (0, flow_variable_processor_1.processFlowOutputs)(outputsConfig, flowDefinitionRecord, factory, diagnostics);
1566
+ relatedRecords.push(...outputRecords);
1567
+ }
1568
+ const allInstances = flowBody?.getStatements().filter((stmt) => !(stmt instanceof sdk_build_core_1.UndefinedShape));
1569
+ // Create lookup maps for flow variables and subflow inputs
1570
+ const flowVarDefMap = (0, label_cache_processor_1.createDefinitionMap)(relatedRecords, 'sys_hub_flow_variable');
1571
+ const subflowInputDefMap = (0, label_cache_processor_1.createDefinitionMap)(relatedRecords, 'sys_hub_flow_input');
1572
+ // Extract trigger data to be used during label cache generation
1573
+ const triggerInstanceShape = isFlow
1574
+ ? callExpression.getArgument(1)?.if(sdk_build_core_1.UndefinedShape)
1575
+ ? undefined
1576
+ : callExpression.getArgument(1)?.as(sdk_build_core_1.CallExpressionShape)
1577
+ : undefined;
1578
+ const triggerData = triggerInstanceShape
1579
+ ? {
1580
+ inputs: (0, label_cache_processor_1.extractTriggerInputs)(triggerInstanceShape),
1581
+ outputs: (0, label_cache_processor_1.extractTriggerOutputs)(triggerInstanceShape),
1582
+ }
1583
+ : undefined;
1584
+ // Map to aggregate data pill metadata for label_cache
1585
+ // biome-ignore lint/suspicious/noExplicitAny: Dynamic label cache entries
1586
+ let labelCacheMap = new Map();
1587
+ // Map to track forEach instances with their metadata for label generation
1588
+ let forEachMetadataMap = new Map();
1589
+ let order = 1;
1590
+ for (const [, v] of (allInstances ?? []).entries()) {
1591
+ // Validate trigger placement: triggers must be the second argument to Flow(), not in the body
1592
+ const callExpr = v instanceof sdk_build_core_1.VariableStatementShape ? v.getInitializer() : v;
1593
+ if (callExpr instanceof sdk_build_core_1.CallExpressionShape && callExpr.getCallee() === flow_constants_1.TRIGGER_INSTANCE_API_NAME) {
1594
+ diagnostics.error(callExpr.getOriginalNode(), 'Trigger instances must be passed as the second argument to Flow(), not inside the flow body');
1595
+ continue;
1596
+ }
1597
+ const instanceRecord = await (0, utils_1.getRecordFromFlowInstaceShape)(v, transform);
1598
+ if (instanceRecord) {
1599
+ instanceRecord.flat().forEach((rec) => {
1600
+ // For subflow instances, values will be in subflow_inputs, for other instances (action/flow logic) it will be in values
1601
+ const inputsKey = rec.getTable() === 'sys_hub_sub_flow_instance_v2' ? 'subflow_inputs' : 'values';
1602
+ let valuesJSON = rec.get(inputsKey)?.getValue() || {};
1603
+ // Post-process setFlowVariables to apply complex object serialization
1604
+ if (rec.getTable() === 'sys_hub_flow_logic_instance_v2') {
1605
+ const valuesObj = valuesJSON;
1606
+ // Process setFlowVariables
1607
+ if (valuesObj.variables && valuesObj.variables.length > 0) {
1608
+ // Create a record-like object that includes all related records for resolveComplexInput
1609
+ // resolveComplexInput calls .flat() on the parentDef to get all records
1610
+ const combinedRecord = {
1611
+ ...flowDefinitionRecord,
1612
+ flat: () => [...flowDefinitionRecord.flat(), ...relatedRecords],
1613
+ };
1614
+ valuesJSON = postProcessSetFlowVariables(valuesJSON, combinedRecord, logger);
1615
+ }
1616
+ // Process assignSubflowOutputs
1617
+ if (valuesObj.outputsToAssign && valuesObj.outputsToAssign.length > 0) {
1618
+ // Create a record-like object that includes all related records for resolveComplexInput
1619
+ // resolveComplexInput calls .flat() on the parentDef to get all records
1620
+ const combinedRecord = {
1621
+ ...flowDefinitionRecord,
1622
+ flat: () => [...flowDefinitionRecord.flat(), ...relatedRecords],
1623
+ };
1624
+ valuesJSON = postProcessAssignSubflowOutputs(valuesJSON, combinedRecord, logger);
1625
+ }
1626
+ }
1627
+ const recUiId = rec.get('ui_id').asString()?.getValue();
1628
+ // Extract data pills from values array and track their usage
1629
+ labelCacheMap = (0, label_cache_processor_1.extractDataPillsFromValuesArray)(valuesJSON, recUiId, labelCacheMap);
1630
+ let finalOrder = order.toString();
1631
+ const previousOrder = order - 1;
1632
+ if (previousOrder > 0) {
1633
+ const previousRecord = relatedRecords.find((r) => r.get('order')?.getValue() === previousOrder.toString());
1634
+ if (previousRecord &&
1635
+ previousRecord.get('logic_definition')?.getValue() === flow_logic_constants_1.DO_IN_PARALLEL_BLOCK_SYS_ID) {
1636
+ finalOrder = `${previousOrder}${flow_plugin_constants_1.PARALLEL_ORDER_SEPARATOR}${order}`;
1637
+ }
1638
+ }
1639
+ // Update forEach metadata for label cache generation
1640
+ forEachMetadataMap = (0, label_cache_processor_1.updateForEachMetadata)(rec, order, flowVarDefMap, forEachMetadataMap);
1641
+ labelCacheMap = (0, label_cache_processor_1.extractLabelCache)(flowVarDefMap, subflowInputDefMap, relatedRecords, labelCacheMap, triggerData, forEachMetadataMap);
1642
+ relatedRecords.push(rec.merge({
1643
+ flow: flowDefinitionRecord.getId().getValue(),
1644
+ order: finalOrder,
1645
+ [inputsKey]: (0, node_zlib_1.gzipSync)(JSON.stringify(valuesJSON)).toString('base64'),
1646
+ }));
1647
+ order++;
1648
+ });
1649
+ }
1650
+ else {
1651
+ diagnostics.error(v.getOriginalNode(), `Unknown instance type in Flow ${flowDefinitionRecord.getId().getValue()}`);
1652
+ }
1653
+ }
1654
+ const labelCacheData = Array.from(labelCacheMap.values());
1655
+ const flowDefWithMetadata = labelCacheData.length > 0
1656
+ ? flowDefinitionRecord.merge({
1657
+ label_cache: JSON.stringify(labelCacheData),
1658
+ })
1659
+ : flowDefinitionRecord;
1660
+ return {
1661
+ success: true,
1662
+ value: flowDefWithMetadata.with(...relatedRecords),
1663
+ };
1664
+ },
1665
+ },
1666
+ ],
1667
+ });
1668
+ //# sourceMappingURL=flow-definition-plugin.js.map