@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,2092 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createEmptyFlowLogicValues = createEmptyFlowLogicValues;
4
+ exports.childrenContainDatapills = childrenContainDatapills;
5
+ exports.isConditionalLogicShape = isConditionalLogicShape;
6
+ exports.isForEachShape = isForEachShape;
7
+ exports.isGoBackToShape = isGoBackToShape;
8
+ exports.isTryCatchShape = isTryCatchShape;
9
+ exports.isDoInParallelShape = isDoInParallelShape;
10
+ exports.isSetFlowVariablesShape = isSetFlowVariablesShape;
11
+ exports.isAssignSubflowOutputsShape = isAssignSubflowOutputsShape;
12
+ exports.isDataPillShape = isDataPillShape;
13
+ exports.getFlowLogicInstanceRecord = getFlowLogicInstanceRecord;
14
+ exports.getFlowLogicArguments = getFlowLogicArguments;
15
+ const sdk_build_core_1 = require("@servicenow/sdk-build-core");
16
+ const data_pill_shapes_1 = require("../utils/data-pill-shapes");
17
+ const zlib_1 = require("zlib");
18
+ const flow_instance_plugin_1 = require("../plugins/flow-instance-plugin");
19
+ const inline_script_plugin_1 = require("../plugins/inline-script-plugin");
20
+ const flow_shapes_1 = require("../utils/flow-shapes");
21
+ const flow_logic_constants_1 = require("./flow-logic-constants");
22
+ const utils_1 = require("../utils/utils");
23
+ const arrow_function_plugin_1 = require("../../arrow-function-plugin");
24
+ const now_id_plugin_1 = require("../../now-id-plugin");
25
+ const flow_logic_diagnostics_1 = require("./flow-logic-diagnostics");
26
+ const flow_data_pill_plugin_1 = require("../plugins/flow-data-pill-plugin");
27
+ async function buildFlowLogicInstanceRecord(expr, factory, values) {
28
+ const partialRecord = await factory.createRecord({
29
+ source: expr,
30
+ table: 'sys_hub_flow_logic_instance_v2',
31
+ explicitId: expr.getSysId(),
32
+ properties: {
33
+ comment: expr.getAnnotation()?.getValue() ?? '',
34
+ logic_definition: flow_logic_constants_1.FlowLogicSysId.getLogicId(expr.getCallee()),
35
+ values: values,
36
+ },
37
+ });
38
+ return partialRecord.merge({ ui_id: (0, utils_1.sysIdToUuid)(partialRecord.getId().getValue()) });
39
+ }
40
+ /**
41
+ * Creates an empty FlowLogicValues object with all fields initialized to empty arrays
42
+ * @returns Empty FlowLogicValues structure
43
+ */
44
+ function createEmptyFlowLogicValues() {
45
+ return {
46
+ inputs: [],
47
+ outputsToAssign: [],
48
+ variables: [],
49
+ decisionTableInputs: [],
50
+ dynamicInputs: [],
51
+ workflowInputs: [],
52
+ };
53
+ }
54
+ /**
55
+ * FlowLogicValueProcessor handles bidirectional conversion between Fluent TypeScript
56
+ * flow logic calls and ServiceNow XML flow records.
57
+ *
58
+ * ## Architecture
59
+ *
60
+ * **Forward Flow (Fluent → XML):**
61
+ * - `prepare()` converts TypeScript flow logic calls to ServiceNow XML format
62
+ * - Extracts configuration properties and creates structured input data
63
+ * - Data gets gzipped and stored in sys_hub_flow_logic_instance_v2 records
64
+ *
65
+ * **Reverse Flow (XML → Fluent):**
66
+ * - `parse()` converts ServiceNow XML records back to TypeScript
67
+ * - Unzips and parses stored JSON data
68
+ * - Reconstructs original configuration objects for shape generation
69
+ *
70
+ * ## Data Structure
71
+ *
72
+ * All flow logic data is stored as FlowLogicValues containing an array of
73
+ * FlowLogicValueInput objects with name/value pairs that represent the
74
+ * original TypeScript configuration properties.
75
+ */
76
+ var FlowLogicValueProcessor;
77
+ (function (FlowLogicValueProcessor) {
78
+ /**
79
+ * Generic factory function for creating flow logic entry objects.
80
+ * All entry types (AssignSubflowOutput, SetFlowVariablesInput, FlowLogicValueInput)
81
+ * share the same structure, differing only in displayValue and type name.
82
+ *
83
+ * @param name - Entry name
84
+ * @param value - Entry value (may contain datapills like "{{trigger.name}}")
85
+ * @param children - Optional children array for complex objects (FlowObject/FlowArray)
86
+ * @param displayValue - Display value shown in ServiceNow UI (defaults to value)
87
+ * @returns Entry object with the specified type
88
+ */
89
+ function createEntry(name, value, children, displayValue = value) {
90
+ return {
91
+ name,
92
+ value,
93
+ displayValue,
94
+ children: children || [],
95
+ parameter: {},
96
+ scriptActive: false,
97
+ };
98
+ }
99
+ function createInput(name, value) {
100
+ return createEntry(name, value);
101
+ }
102
+ /**
103
+ * Creates an AssignSubflowOutput entry with full display value.
104
+ * Used when generating XML from Fluent code for assignSubflowOutputs.
105
+ *
106
+ * @param name - Output name
107
+ * @param value - Output value (may contain datapills like "{{trigger.name}}")
108
+ * @param children - Optional children array for complex objects (FlowObject/FlowArray)
109
+ * @returns AssignSubflowOutput with displayValue set to the value
110
+ */
111
+ function createOutput(name, value, children) {
112
+ return createEntry(name, value, children);
113
+ }
114
+ /**
115
+ * Creates a SetFlowVariablesInput entry for the 'variables' array with full display value.
116
+ * Used when generating XML from Fluent code.
117
+ *
118
+ * @param name - Variable name
119
+ * @param value - Variable value (may contain datapills like "{{trigger.name}}")
120
+ * @param children - Optional children array for complex objects (FlowObject/FlowArray)
121
+ * @returns SetFlowVariablesInput with displayValue set to the value
122
+ */
123
+ function createVariable(name, value, children) {
124
+ return createEntry(name, value, children);
125
+ }
126
+ /**
127
+ * Creates a SetFlowVariablesInput entry for the 'inputs' array with empty display value.
128
+ * Used when generating XML from Fluent code for the inputs array (required for backward compatibility).
129
+ *
130
+ * @param name - Variable name
131
+ * @param value - Variable value
132
+ * @param children - Optional children array for complex objects (FlowObject/FlowArray)
133
+ * @returns SetFlowVariablesInput with empty displayValue
134
+ */
135
+ function createVariableInput(name, value, children) {
136
+ return createEntry(name, value, children, '');
137
+ }
138
+ const INPUT_VALUE_PREPARERS = {
139
+ [flow_logic_constants_1.FLOW_LOGIC.ELSE]: () => [],
140
+ [flow_logic_constants_1.FLOW_LOGIC.GOBACKTO]: (data) => prepareGoBackTo(data.isString() ? data.asString() : data.asRecord()),
141
+ [flow_logic_constants_1.FLOW_LOGIC.IF]: (data) => prepareIfElse(data.asObject()),
142
+ [flow_logic_constants_1.FLOW_LOGIC.ELSEIF]: (data) => prepareIfElse(data.asObject()),
143
+ [flow_logic_constants_1.FLOW_LOGIC.WAIT_FOR_A_DURATION]: (data) => prepareWaitForADuration(data.asObject()),
144
+ [flow_logic_constants_1.FLOW_LOGIC.EXITLOOP]: () => [],
145
+ [flow_logic_constants_1.FLOW_LOGIC.ENDFLOW]: () => [],
146
+ [flow_logic_constants_1.FLOW_LOGIC.SKIP_ITERATION]: () => [],
147
+ [flow_logic_constants_1.FLOW_LOGIC.FOR_EACH]: (data) => prepareForEach(data.asString()),
148
+ [flow_logic_constants_1.FLOW_LOGIC.DO_IN_PARALLEL]: () => [],
149
+ [flow_logic_constants_1.FLOW_LOGIC.TRY_CATCH]: () => [],
150
+ [flow_logic_constants_1.FLOW_LOGIC.SET_FLOW_VARIABLES]: (data) => {
151
+ return prepareSetFlowVariables(data.asObject(), '');
152
+ },
153
+ [flow_logic_constants_1.FLOW_LOGIC.ASSIGN_SUBFLOW_OUTPUTS]: (data) => {
154
+ return prepareAssignSubflowOutputs(data.asObject());
155
+ },
156
+ };
157
+ /**
158
+ * Converts Fluent TypeScript flow logic calls into ServiceNow XML format.
159
+ *
160
+ * **Process:**
161
+ * 1. Takes the flow logic type (e.g., 'IF') and configuration data
162
+ * 2. Uses the appropriate VALUE_PREPARER function
163
+ * 3. Extracts relevant properties (condition, label, etc.)
164
+ * 4. Creates FlowLogicValueInput objects with name/value pairs
165
+ * 5. Returns FlowLogicValues structure that gets gzipped into XML
166
+ *
167
+ * **Example:**
168
+ * ```typescript
169
+ * // Input: If({ condition: "user.role === 'admin'", label: "Admin Check" })
170
+ * // Output: { inputs: [
171
+ * // { name: 'condition_name', value: 'Admin Check' },
172
+ * // { name: 'condition', value: "user.role === 'admin'" }
173
+ * // ]}
174
+ * ```
175
+ *
176
+ * @param logicType - The flow logic type key (e.g., 'IF', 'ELSEIF', 'GOBACKTO')
177
+ * @param data - Configuration data from the Fluent TypeScript call
178
+ * @param args - Optional arguments including childNameMetadata for FlowArray fields
179
+ * @returns FlowLogicValues structure ready for XML serialization
180
+ */
181
+ function prepare(logicType, data, args) {
182
+ const preparer = INPUT_VALUE_PREPARERS[logicType];
183
+ if (!preparer) {
184
+ throw new Error(`Unsupported flow logic type: ${logicType}`);
185
+ }
186
+ const preparedData = preparer(data, args);
187
+ return {
188
+ outputsToAssign: logicType === flow_logic_constants_1.FLOW_LOGIC.ASSIGN_SUBFLOW_OUTPUTS ? preparedData : [],
189
+ variables: logicType === flow_logic_constants_1.FLOW_LOGIC.SET_FLOW_VARIABLES
190
+ ? prepareSetFlowVariables(data.asObject(), 'variables')
191
+ : [],
192
+ decisionTableInputs: [],
193
+ dynamicInputs: [],
194
+ workflowInputs: [],
195
+ inputs: logicType === flow_logic_constants_1.FLOW_LOGIC.ASSIGN_SUBFLOW_OUTPUTS ? [] : preparedData,
196
+ };
197
+ }
198
+ FlowLogicValueProcessor.prepare = prepare;
199
+ function prepareIfElse(config) {
200
+ const inputs = [];
201
+ // After datapill resolution, values are already resolved strings, so use getValue() directly
202
+ const conditionValue = config.get('condition')?.getValue();
203
+ const conditionString = typeof conditionValue === 'string' ? conditionValue : String(conditionValue ?? '');
204
+ const labelValue = config.get('label')?.getValue();
205
+ const label = labelValue && typeof labelValue === 'string' ? labelValue : '';
206
+ if (!conditionString) {
207
+ return [];
208
+ }
209
+ if (label) {
210
+ inputs.push(createInput('condition_name', label));
211
+ }
212
+ inputs.push(createInput('condition', conditionString));
213
+ return inputs;
214
+ }
215
+ function prepareGoBackTo(step) {
216
+ const stepId = step.isRecord() ? step.get('ui_id').asString().getValue() : step.asString().getValue();
217
+ return [createInput('go_back_to_step', stepId)];
218
+ }
219
+ function prepareForEach(config) {
220
+ // ForEach needs to extract the items array from the first argument
221
+ // The structure is: ForEach(items, config, body)
222
+ // For now, we create a basic items input descriptor based on the XML structure we found
223
+ const inputs = [];
224
+ // Create the items input descriptor based on the XML structure we found
225
+ const itemsInput = {
226
+ name: 'items',
227
+ value: config.getValue(),
228
+ displayValue: config.getValue(),
229
+ };
230
+ inputs.push(itemsInput);
231
+ return inputs;
232
+ }
233
+ function prepareWaitForADuration(config) {
234
+ const inputDescriptors = JSON.parse(JSON.stringify(flow_logic_constants_1.WAIT_FOR_A_DURATION_INPUT_DESCRIPTORS));
235
+ // Helper to safely get config value as string (after datapill resolution, values are already resolved)
236
+ const getConfigValue = (key) => {
237
+ const value = config.get(key)?.getValue();
238
+ return value !== undefined && value !== null ? String(value) : '';
239
+ };
240
+ // Map the instanceProps to the correct fields in the template
241
+ // durationType: explicit_duration | relative_duration | percentage_duration
242
+ const durationType = getConfigValue('durationType');
243
+ // Duration field is optional (not required for percentage_duration)
244
+ const durationField = config.get('duration');
245
+ const duration = durationField && !durationField.isUndefined()
246
+ ? new sdk_build_core_1.DurationShape({
247
+ source: config.getOriginalNode(),
248
+ value: durationField.getValue(),
249
+ })
250
+ : durationField;
251
+ const schedule = getConfigValue('schedule');
252
+ const durationTypeDisplayMap = {
253
+ explicit_duration: 'Explicit duration',
254
+ relative_duration: 'Relative duration',
255
+ percentage_duration: 'Percentage duration',
256
+ };
257
+ const updateDescriptor = (index, value, displayValue, parameterType) => {
258
+ if (inputDescriptors[index]) {
259
+ inputDescriptors[index].value = value;
260
+ inputDescriptors[index].displayValue = displayValue ?? value;
261
+ // Add parameter.type to preserve type information for round-trip transformation
262
+ if (parameterType) {
263
+ inputDescriptors[index].parameter = { type: parameterType };
264
+ }
265
+ }
266
+ };
267
+ updateDescriptor(0, durationType, durationTypeDisplayMap[durationType]);
268
+ const durationValue = duration?.toString()?.getValue() || '';
269
+ // Include 'glide_duration' type so XML → Fluent transform knows to create DurationShape
270
+ updateDescriptor(3, durationValue, durationValue, 'glide_duration');
271
+ updateDescriptor(6, schedule);
272
+ if (durationType === 'relative_duration') {
273
+ updateDescriptor(4, getConfigValue('relativeOperator'));
274
+ updateDescriptor(5, getConfigValue('relativeDatetime'));
275
+ }
276
+ if (durationType === 'percentage_duration') {
277
+ updateDescriptor(2, getConfigValue('percentage'));
278
+ updateDescriptor(1, getConfigValue('percentageDatetime'));
279
+ }
280
+ return inputDescriptors;
281
+ }
282
+ /**
283
+ * Checks if a value is a serialized inline script object.
284
+ * Inline script objects have the shape: { scriptActive: true, script: {...}, name, value, ... }
285
+ *
286
+ * @param value - The value to check
287
+ * @returns true if value is an inline script object, false otherwise
288
+ */
289
+ function isSerializedInlineScript(value) {
290
+ return (typeof value === 'object' &&
291
+ value !== null &&
292
+ !Array.isArray(value) &&
293
+ value.scriptActive === true);
294
+ }
295
+ /**
296
+ * Builds a flattened children array from a nested object or array.
297
+ * Used for the 'children' field in SetFlowVariablesInput for complex objects (FlowObject/FlowArray).
298
+ *
299
+ * @param value - The object or array value
300
+ * @param childName - Optional childName for FlowArray elements (e.g., 'tag', 'color')
301
+ * @returns Array of child entries with name, value, displayValue, and scriptActive fields
302
+ */
303
+ function buildChildrenArray(value, childName) {
304
+ const children = [];
305
+ if (Array.isArray(value)) {
306
+ // FlowArray: Create a child entry for each array element
307
+ // Use childName if provided (matches UI behavior), otherwise empty string (backward compatibility)
308
+ const elementName = childName || '';
309
+ for (const element of value) {
310
+ if (typeof element === 'object' && element !== null) {
311
+ // Nested object in array
312
+ children.push({
313
+ name: elementName,
314
+ value: '',
315
+ displayValue: '',
316
+ children: buildChildrenArray(element),
317
+ scriptActive: false,
318
+ });
319
+ }
320
+ else {
321
+ // Primitive in array
322
+ const elementStr = element === null || element === undefined || element === '' ? '' : String(element);
323
+ children.push({
324
+ name: elementName,
325
+ value: elementStr,
326
+ displayValue: elementStr,
327
+ scriptActive: false,
328
+ });
329
+ }
330
+ }
331
+ }
332
+ else if (typeof value === 'object' && value !== null) {
333
+ // FlowObject: Create a child entry for each field
334
+ for (const [fieldName, fieldValue] of Object.entries(value)) {
335
+ if (typeof fieldValue === 'object' && fieldValue !== null && !Array.isArray(fieldValue)) {
336
+ // Nested object
337
+ children.push({
338
+ name: fieldName,
339
+ value: '',
340
+ displayValue: '',
341
+ children: buildChildrenArray(fieldValue),
342
+ scriptActive: false,
343
+ });
344
+ }
345
+ else if (Array.isArray(fieldValue)) {
346
+ // Nested array - Note: nested arrays don't have childName metadata yet
347
+ children.push({
348
+ name: fieldName,
349
+ value: '',
350
+ displayValue: '',
351
+ children: buildChildrenArray(fieldValue),
352
+ scriptActive: false,
353
+ });
354
+ }
355
+ else {
356
+ // Primitive field
357
+ const fieldStr = fieldValue === null || fieldValue === undefined || fieldValue === '' ? '' : String(fieldValue);
358
+ children.push({
359
+ name: fieldName,
360
+ value: fieldStr,
361
+ displayValue: fieldStr,
362
+ scriptActive: false,
363
+ });
364
+ }
365
+ }
366
+ }
367
+ return children;
368
+ }
369
+ /**
370
+ * Generic helper to prepare entries from ObjectShape for XML serialization.
371
+ * Extracts key-value pairs and applies a factory function to create typed entries.
372
+ *
373
+ * Handles inline script objects (with scriptActive: true) by returning them as-is.
374
+ * Also handles complex objects (FlowObject/FlowArray) by building children arrays.
375
+ *
376
+ * @param values - ObjectShape containing name-value pairs from Fluent code
377
+ * @param factory - Factory function to create entry objects from key-value pairs
378
+ * @param childNameMetadata - Optional map of field name → childName for FlowArray fields
379
+ * @param useDottedNames - If true, use "fieldName.childName" format for array elements (assignSubflowOutputs)
380
+ * @returns Array of entries ready for XML serialization
381
+ */
382
+ function prepareEntries(values, factory) {
383
+ if (!values || values.isUndefined()) {
384
+ return [];
385
+ }
386
+ const results = [];
387
+ const entries = values.entries({ resolve: false });
388
+ for (const [key, shape] of entries) {
389
+ // Check if the shape is an ObjectShape (for FlowObject assignments)
390
+ if (shape.is(sdk_build_core_1.ObjectShape)) {
391
+ const serializedObj = serializeShapeToValue(shape);
392
+ // Check if the serialized value is an inline script (has scriptActive: true)
393
+ if (isSerializedInlineScript(serializedObj)) {
394
+ // Inline scripts are already in the correct format - return as-is
395
+ results.push(serializedObj);
396
+ continue;
397
+ }
398
+ // Regular FlowObject - children with correct names will be added by resolveComplexInput in postProcess
399
+ const children = buildChildrenArray(serializedObj);
400
+ results.push(factory(key, JSON.stringify(serializedObj), children));
401
+ continue;
402
+ }
403
+ // Check if the shape is an ArrayShape (for FlowArray assignments)
404
+ if (shape.is(sdk_build_core_1.ArrayShape)) {
405
+ const arrShape = shape.as(sdk_build_core_1.ArrayShape);
406
+ const serializedArr = [];
407
+ for (const elem of arrShape.getElements()) {
408
+ serializedArr.push(serializeShapeToValue(elem));
409
+ }
410
+ // Children with correct names will be added by resolveComplexInput in postProcess
411
+ const children = buildChildrenArray(serializedArr);
412
+ results.push(factory(key, JSON.stringify(serializedArr), children));
413
+ continue;
414
+ }
415
+ // For all other shapes, get their value
416
+ const value = shape.getValue();
417
+ // Check if value is a serialized inline script object
418
+ if (isSerializedInlineScript(value)) {
419
+ // Inline scripts are already in the correct format - return as-is
420
+ results.push(value);
421
+ continue;
422
+ }
423
+ // Check if value is a plain object or array (shouldn't happen but just in case)
424
+ if (typeof value === 'object' && value !== null) {
425
+ const children = buildChildrenArray(value);
426
+ results.push(factory(key, JSON.stringify(value), children));
427
+ continue;
428
+ }
429
+ // Primitive values (string, number, boolean, datapills)
430
+ results.push(factory(key, String(value)));
431
+ }
432
+ return results;
433
+ }
434
+ /**
435
+ * Recursively serializes a Shape to a plain JavaScript value, preserving datapills as pill strings.
436
+ * @param shape - The shape to serialize
437
+ * @returns Plain JavaScript value with datapills as strings like "{{trigger.name}}"
438
+ */
439
+ function serializeShapeToValue(shape) {
440
+ if (shape.is(sdk_build_core_1.ObjectShape)) {
441
+ const obj = {};
442
+ for (const [key, valueShape] of shape.as(sdk_build_core_1.ObjectShape).entries({ resolve: false })) {
443
+ obj[key] = serializeShapeToValue(valueShape);
444
+ }
445
+ return obj;
446
+ }
447
+ if (shape.is(sdk_build_core_1.ArrayShape)) {
448
+ const arr = [];
449
+ for (const elem of shape.as(sdk_build_core_1.ArrayShape).getElements()) {
450
+ arr.push(serializeShapeToValue(elem));
451
+ }
452
+ return arr;
453
+ }
454
+ // Handle TemplateExpressionShape (template strings with datapills)
455
+ if (shape.is(sdk_build_core_1.TemplateExpressionShape)) {
456
+ // TemplateExpressionShape should have been converted to PillTemplateShape by DataPillPlugin
457
+ // If it's a PillTemplateShape, get its value
458
+ if (shape.is(data_pill_shapes_1.PillTemplateShape)) {
459
+ return shape.as(data_pill_shapes_1.PillTemplateShape).getValue();
460
+ }
461
+ // Otherwise, get the regular value
462
+ return shape.getValue();
463
+ }
464
+ // Handle PillShape (wfa.dataPill() is converted to PillShape by WfaDataPillPlugin)
465
+ if (shape.is(data_pill_shapes_1.PillShape)) {
466
+ return shape.as(data_pill_shapes_1.PillShape).getValue();
467
+ }
468
+ // For all other shapes (primitives, etc.), get the value
469
+ return shape.getValue();
470
+ }
471
+ /**
472
+ * Prepares SetFlowVariables data for XML serialization.
473
+ * Converts an ObjectShape containing variable assignments into an array of SetFlowVariablesInput entries.
474
+ *
475
+ * The `type` parameter determines which array format to use:
476
+ * - 'variables': Creates entries with full displayValue (for the 'variables' array in XML)
477
+ * - default: Creates entries with empty displayValue (for the 'inputs' array in XML)
478
+ *
479
+ * This dual behavior is required because ServiceNow stores SetFlowVariables data in both
480
+ * the 'variables' array and the 'inputs' array for backward compatibility.
481
+ *
482
+ * @param values - ObjectShape containing variable name-value pairs from Fluent code
483
+ * @param type - Optional type flag ('variables' for variables array, default for inputs array)
484
+ * @returns Array of SetFlowVariablesInput entries ready for XML serialization
485
+ *
486
+ * @example
487
+ * // Fluent: { user: params.trigger.name, count: 42 }
488
+ * // Variables array: [{ name: 'user', value: '{{trigger.name}}', displayValue: '{{trigger.name}}' }, ...]
489
+ * // Inputs array: [{ name: 'user', value: '{{trigger.name}}', displayValue: '' }, ...]
490
+ */
491
+ function prepareSetFlowVariables(values, type = '') {
492
+ return prepareEntries(values, (key, value, children) => {
493
+ // Choose appropriate creator based on type flag
494
+ if (type === 'variables') {
495
+ return createVariable(key, value, children);
496
+ }
497
+ else {
498
+ return createVariableInput(key, value, children);
499
+ }
500
+ });
501
+ }
502
+ /**
503
+ * Prepares AssignSubflowOutputs data for XML serialization.
504
+ * Converts an ObjectShape containing output assignments into an array of AssignSubflowOutput entries.
505
+ *
506
+ * @param values - ObjectShape containing output name-value pairs from Fluent code
507
+ * @returns Array of AssignSubflowOutput entries ready for XML serialization
508
+ *
509
+ * @example
510
+ * // Fluent: { result: params.action.output, status: 'complete' }
511
+ * // XML: [{ name: 'result', value: '{{action.output}}', displayValue: '{{action.output}}', scriptActive: false }, ...]
512
+ *
513
+ * Note: childName for FlowArray fields is now set automatically by resolveComplexInput in postProcess functions
514
+ */
515
+ function prepareAssignSubflowOutputs(values) {
516
+ return prepareEntries(values, createOutput);
517
+ }
518
+ const VALUE_PARSERS = {
519
+ [flow_logic_constants_1.FLOW_LOGIC.GOBACKTO]: parseGoBackTo,
520
+ [flow_logic_constants_1.FLOW_LOGIC.IF]: parseIfElse,
521
+ [flow_logic_constants_1.FLOW_LOGIC.ELSEIF]: parseIfElse,
522
+ [flow_logic_constants_1.FLOW_LOGIC.ELSE]: parseIfElse,
523
+ [flow_logic_constants_1.FLOW_LOGIC.WAIT_FOR_A_DURATION]: () => ({}),
524
+ [flow_logic_constants_1.FLOW_LOGIC.EXITLOOP]: () => ({}),
525
+ [flow_logic_constants_1.FLOW_LOGIC.ENDFLOW]: () => ({}),
526
+ [flow_logic_constants_1.FLOW_LOGIC.SKIP_ITERATION]: () => ({}),
527
+ [flow_logic_constants_1.FLOW_LOGIC.FOR_EACH]: parseForEach,
528
+ [flow_logic_constants_1.FLOW_LOGIC.DO_IN_PARALLEL]: () => ({}),
529
+ [flow_logic_constants_1.FLOW_LOGIC.TRY_CATCH]: () => ({}),
530
+ [flow_logic_constants_1.FLOW_LOGIC.SET_FLOW_VARIABLES]: () => ({}),
531
+ [flow_logic_constants_1.FLOW_LOGIC.ASSIGN_SUBFLOW_OUTPUTS]: () => ({}),
532
+ };
533
+ /**
534
+ * Converts ServiceNow XML flow logic records back to Fluent TypeScript.
535
+ *
536
+ * **Process:**
537
+ * 1. Takes gzipped JSON string from XML record
538
+ * 2. Unzips and parses the FlowLogicValues structure
539
+ * 3. Uses the appropriate VALUE_PARSER function
540
+ * 4. Reconstructs the original configuration object
541
+ * 5. Returns structured data for shape generation
542
+ *
543
+ * **Example:**
544
+ * ```typescript
545
+ * // Input: gzipped JSON with inputs array
546
+ * // Output: { condition: "user.role === 'admin'", label: "Admin Check" /**
547
+ * Parses flow logic values from gzipped JSON string
548
+ * @param logicType - The flow logic type key (e.g., 'IF', 'ELSEIF', 'GOBACKTO')
549
+ * @param gZippedString - Base64 encoded gzipped JSON from XML record
550
+ * @param typeMap - Optional map of variable/output names to their internal types for proper type conversion
551
+ * @param labelCacheMap - Optional map of datapill names to their types from the label cache
552
+ * @returns Parsed configuration object for TypeScript shape generation
553
+ */
554
+ function parse(logicType, gZippedString, typeMap, labelCacheMap) {
555
+ const valuesJson = parseGzippedJson(gZippedString);
556
+ // Special handling for SET_FLOW_VARIABLES - data is in variables array
557
+ if (logicType === flow_logic_constants_1.FLOW_LOGIC.SET_FLOW_VARIABLES) {
558
+ if (valuesJson?.variables?.length) {
559
+ return parseEntriesFromArray(valuesJson.variables, typeMap, labelCacheMap);
560
+ }
561
+ return {};
562
+ }
563
+ // Special handling for ASSIGN_SUBFLOW_OUTPUTS - data is in outputsToAssign array
564
+ if (logicType === flow_logic_constants_1.FLOW_LOGIC.ASSIGN_SUBFLOW_OUTPUTS) {
565
+ if (valuesJson?.outputsToAssign?.length) {
566
+ return parseEntriesFromArray(valuesJson.outputsToAssign, typeMap, labelCacheMap);
567
+ }
568
+ return {};
569
+ }
570
+ if (!valuesJson?.inputs?.length) {
571
+ if (logicType === flow_logic_constants_1.FLOW_LOGIC.GOBACKTO) {
572
+ throw new Error('Malformed/unsupported input payload in GoBackTo Instance');
573
+ }
574
+ return {};
575
+ }
576
+ const parser = VALUE_PARSERS[logicType];
577
+ if (!parser) {
578
+ throw new Error(`Unsupported flow logic type for parsing: ${logicType}`);
579
+ }
580
+ return parser(valuesJson.inputs);
581
+ }
582
+ FlowLogicValueProcessor.parse = parse;
583
+ function parseGzippedJson(gZippedString) {
584
+ try {
585
+ const unzipped = (0, zlib_1.gunzipSync)(Buffer.from(gZippedString, 'base64')).toString();
586
+ return JSON.parse(unzipped);
587
+ }
588
+ catch {
589
+ return null;
590
+ }
591
+ }
592
+ function parseIfElse(inputs) {
593
+ const result = {};
594
+ for (const input of inputs) {
595
+ if (input.name === 'condition' && input.value) {
596
+ result.condition = input.value;
597
+ }
598
+ else if (input.name === 'condition_name' && input.value) {
599
+ result.label = input.value;
600
+ }
601
+ }
602
+ return result;
603
+ }
604
+ function parseGoBackTo(inputs) {
605
+ for (const input of inputs) {
606
+ if (input.name === 'go_back_to_step' && input.value) {
607
+ return input.value;
608
+ }
609
+ }
610
+ throw new Error('Malformed/unsupported input payload in GoBackTo Instance');
611
+ }
612
+ function parseForEach(inputs) {
613
+ const result = {};
614
+ for (const input of inputs) {
615
+ if (input.name === 'items' && input.value) {
616
+ result.items = input.value;
617
+ }
618
+ }
619
+ return result;
620
+ }
621
+ // Constants for type handling
622
+ const ARRAY_TYPE_PREFIX = 'array.';
623
+ const ARRAY_TYPE_PREFIX_LENGTH = ARRAY_TYPE_PREFIX.length;
624
+ const EXCLUDED_TYPE_ANNOTATIONS = new Set(['string', 'glide_date_time']);
625
+ /**
626
+ * Extracts the base name from a dotted path (e.g., "project.name" -> "name")
627
+ * For assignSubflowOutputs, names are prefixed with parent (e.g., "project.name", "project.tasks")
628
+ * We need to strip the prefix to get the actual field name
629
+ * @param name - Full path name
630
+ * @returns Base name after the last dot
631
+ */
632
+ function getBaseName(name) {
633
+ if (!name) {
634
+ return '';
635
+ }
636
+ const lastDot = name.lastIndexOf('.');
637
+ return lastDot >= 0 ? name.substring(lastDot + 1) : name;
638
+ }
639
+ /**
640
+ * Extracts element type from array type string
641
+ * @param type - Type string like "array.integer" or "string"
642
+ * @returns Element type or undefined
643
+ */
644
+ function extractArrayElementType(type) {
645
+ if (!type || !type.startsWith(ARRAY_TYPE_PREFIX)) {
646
+ return undefined;
647
+ }
648
+ return type.substring(ARRAY_TYPE_PREFIX_LENGTH);
649
+ }
650
+ /**
651
+ * Strip type annotation from datapill strings.
652
+ * ServiceNow stores datapills with type annotations like {{trigger.name|string}}.
653
+ * We need to remove the |type part before creating PropertyAccessShape.
654
+ *
655
+ * @param value - The value to clean (may be datapill string or regular value)
656
+ * @returns Cleaned value with type annotation removed
657
+ */
658
+ function stripDatapillTypeAnnotation(value) {
659
+ // Check if this is a datapill string (starts with {{ and ends with }})
660
+ if (value.startsWith('{{') && value.endsWith('}}')) {
661
+ // Extract content between {{ and }}
662
+ const content = value.slice(2, -2);
663
+ // Split by | and take only the first part (the path without type annotation)
664
+ const pathOnly = content.split('|')[0];
665
+ // Return cleaned datapill
666
+ return `{{${pathOnly}}}`;
667
+ }
668
+ // Not a datapill, return as-is
669
+ return value;
670
+ }
671
+ /**
672
+ * Adds type annotation to a datapill if needed based on label cache
673
+ * @param pillName - Datapill name without braces
674
+ * @param labelCacheMap - Map of datapill names to types
675
+ * @returns Datapill with annotation if applicable
676
+ */
677
+ function addTypeAnnotationIfNeeded(pillName, labelCacheMap) {
678
+ if (!labelCacheMap) {
679
+ return `{{${pillName}}}`;
680
+ }
681
+ const cachedType = labelCacheMap.get(pillName.trim());
682
+ if (cachedType && !EXCLUDED_TYPE_ANNOTATIONS.has(cachedType)) {
683
+ return `{{${pillName}|${cachedType}}}`;
684
+ }
685
+ return `{{${pillName}}}`;
686
+ }
687
+ /**
688
+ * Processes a pure datapill value (starts and ends with {{}})
689
+ * @param value - Pure datapill string
690
+ * @param labelCacheMap - Map of datapill names to types
691
+ * @returns Processed datapill with type annotation if needed
692
+ */
693
+ function processPureDatapill(value, labelCacheMap) {
694
+ const strippedValue = stripDatapillTypeAnnotation(value);
695
+ const pillName = strippedValue.slice(2, -2); // Remove {{ and }}
696
+ return addTypeAnnotationIfNeeded(pillName, labelCacheMap);
697
+ }
698
+ /**
699
+ * Processes a template expression containing datapills mixed with text
700
+ * @param value - Template expression string
701
+ * @param labelCacheMap - Map of datapill names to types
702
+ * @returns Processed template with type annotations added to datapills
703
+ */
704
+ function processTemplateExpression(value, labelCacheMap) {
705
+ if (!labelCacheMap) {
706
+ return value;
707
+ }
708
+ const datapillRegex = /\{\{([^}|]+)(?:\|[^}]+)?\}\}/g;
709
+ return value.replace(datapillRegex, (_match, pillName) => addTypeAnnotationIfNeeded(pillName, labelCacheMap));
710
+ }
711
+ /**
712
+ * Converts a primitive value based on its type
713
+ * @param value - String value to convert
714
+ * @param uiType - Type information
715
+ * @returns Converted value
716
+ */
717
+ function convertPrimitiveValue(value, uiType) {
718
+ // Preserve empty strings - don't convert them to 0 or false
719
+ if (value === '') {
720
+ return value;
721
+ }
722
+ if (uiType === 'integer') {
723
+ const num = Number(value);
724
+ return Number.isNaN(num) ? value : num;
725
+ }
726
+ if (uiType === 'boolean') {
727
+ if (value === 'true' || value === '1') {
728
+ return true;
729
+ }
730
+ if (value === 'false' || value === '0') {
731
+ return false;
732
+ }
733
+ return value;
734
+ }
735
+ return stripDatapillTypeAnnotation(value);
736
+ }
737
+ /**
738
+ * Recursively applies type conversion to an object and its nested objects
739
+ * @param obj - Object to apply type conversion to
740
+ * @param typeMap - Map of field names to their types
741
+ * @returns Object with type-converted values
742
+ */
743
+ function applyTypeConversionToObject(obj, typeMap) {
744
+ if (typeof obj !== 'object' || obj === null) {
745
+ return obj;
746
+ }
747
+ if (Array.isArray(obj)) {
748
+ return obj;
749
+ }
750
+ const result = {};
751
+ for (const [key, value] of Object.entries(obj)) {
752
+ const fieldType = typeMap.get(key);
753
+ if (typeof value === 'string' && fieldType) {
754
+ result[key] = convertPrimitiveValue(value, fieldType);
755
+ }
756
+ else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
757
+ // Recursively apply to nested objects
758
+ result[key] = applyTypeConversionToObject(value, typeMap);
759
+ }
760
+ else {
761
+ result[key] = value;
762
+ }
763
+ }
764
+ return result;
765
+ }
766
+ /**
767
+ * Converts a string value to the appropriate type based on uiType
768
+ * @param value - String value to convert
769
+ * @param uiType - Type information from parameter (e.g., 'integer', 'boolean', 'string')
770
+ * @param labelCacheMap - Optional map of datapill names to their types from the label cache
771
+ * @returns Properly typed value
772
+ */
773
+ function convertChildValueToType(value, uiType, labelCacheMap) {
774
+ // Check if value contains datapills (either pure datapill or template expression)
775
+ if (value.includes('{{') && value.includes('}}')) {
776
+ if (value.startsWith('{{') && value.endsWith('}}')) {
777
+ // Pure datapill
778
+ return processPureDatapill(value, labelCacheMap);
779
+ }
780
+ // Template expression with datapills
781
+ return processTemplateExpression(value, labelCacheMap);
782
+ }
783
+ // Non-datapill value - convert based on type
784
+ return convertPrimitiveValue(value, uiType);
785
+ }
786
+ /**
787
+ * Extracts the element type from a parent entry for primitive arrays.
788
+ * Parses the complexObjectSchema from the parent's value to get child_type.
789
+ *
790
+ * @param parentEntry - Parent entry containing the schema information
791
+ * @returns Element type (e.g., 'integer', 'boolean', 'string') or undefined
792
+ */
793
+ function getArrayElementType(parentEntry) {
794
+ if (!parentEntry.value || typeof parentEntry.value !== 'string') {
795
+ return undefined;
796
+ }
797
+ try {
798
+ const parsed = JSON.parse(parentEntry.value);
799
+ if (parsed.complexObjectSchema) {
800
+ // Find the $COCollectionField.$type_facets
801
+ for (const schemaKey in parsed.complexObjectSchema) {
802
+ const schema = parsed.complexObjectSchema[schemaKey];
803
+ if (schema && schema.$COCollectionField && schema['$COCollectionField.$type_facets']) {
804
+ const typeFacets = schema['$COCollectionField.$type_facets'];
805
+ if (typeFacets.SimpleMapFacet) {
806
+ const facetData = JSON.parse(typeFacets.SimpleMapFacet);
807
+ return facetData.child_type;
808
+ }
809
+ }
810
+ }
811
+ }
812
+ }
813
+ catch {
814
+ // Ignore parsing errors
815
+ }
816
+ return undefined;
817
+ }
818
+ /**
819
+ * Extracts type schema from a parent entry's complexObjectSchema.
820
+ * The schema contains nested field type information that can be used for type conversion.
821
+ *
822
+ * @param parentEntry - Parent entry containing the schema in its value field
823
+ * @returns Map of field paths to their types (e.g., 'timeout' -> 'integer')
824
+ */
825
+ function extractNestedTypeSchema(parentEntry) {
826
+ const typeMap = new Map();
827
+ if (!parentEntry.value || typeof parentEntry.value !== 'string') {
828
+ return undefined;
829
+ }
830
+ try {
831
+ const parsed = JSON.parse(parentEntry.value);
832
+ const complexObjectSchema = parsed.complexObjectSchema;
833
+ if (!complexObjectSchema) {
834
+ return undefined;
835
+ }
836
+ // Iterate through schema keys (e.g., "FlowDesigner:FD8fc76f46892b4980af21eb5f7b164ef2")
837
+ for (const schemaKey in complexObjectSchema) {
838
+ const schema = complexObjectSchema[schemaKey];
839
+ if (!schema || typeof schema !== 'object') {
840
+ continue;
841
+ }
842
+ // Extract field types from the schema
843
+ for (const fieldName in schema) {
844
+ if (fieldName.endsWith('.$field_facets') || fieldName.endsWith('.$type_facets')) {
845
+ continue;
846
+ }
847
+ const fieldValue = schema[fieldName];
848
+ // Check if this is a nested object with its own fields
849
+ if (typeof fieldValue === 'object' && fieldValue !== null) {
850
+ // Nested object - recursively extract types
851
+ for (const nestedFieldName in fieldValue) {
852
+ if (nestedFieldName.endsWith('.$field_facets')) {
853
+ continue;
854
+ }
855
+ const nestedType = fieldValue[nestedFieldName];
856
+ if (typeof nestedType === 'string') {
857
+ // Map nested field names (e.g., 'timeout' under 'settings')
858
+ typeMap.set(nestedFieldName, nestedType.toLowerCase());
859
+ }
860
+ }
861
+ }
862
+ else if (typeof fieldValue === 'string') {
863
+ // Direct type (e.g., "Integer", "Boolean", "String")
864
+ typeMap.set(fieldName, fieldValue.toLowerCase());
865
+ }
866
+ }
867
+ }
868
+ return typeMap.size > 0 ? typeMap : undefined;
869
+ }
870
+ catch {
871
+ // Ignore parsing errors
872
+ return undefined;
873
+ }
874
+ }
875
+ /**
876
+ * Recursively parses children array to reconstruct nested objects and arrays
877
+ * @param children - Array of child entries with name, value, and optional nested children
878
+ * @param elementType - Type hint for array elements (e.g., 'string', 'integer')
879
+ * @param nestedTypeMap - Optional map of field names to types for nested FlowObjects
880
+ * @param complexObjectData - Optional complex object data for merging with children
881
+ * @param labelCacheMap - Optional map of datapill names to their types from the label cache
882
+ * @returns Reconstructed nested object or array
883
+ */
884
+ function parseChildrenArray(children, elementType, nestedTypeMap, complexObjectData, labelCacheMap) {
885
+ if (!Array.isArray(children) || children.length === 0) {
886
+ return undefined;
887
+ }
888
+ // Check if this is an array or object:
889
+ // - Array (SDK): all children have empty names
890
+ // - Array (UI): all children have the SAME non-empty name (childName repeated)
891
+ // - Object: children have different names (field names)
892
+ const childObj = children[0];
893
+ const firstBaseName = getBaseName(childObj.name);
894
+ // Check if all children have the same base name (indicating FlowArray with repeated childName)
895
+ const allSameName = children.length > 1 &&
896
+ children.every((c) => {
897
+ const entry = c;
898
+ return getBaseName(entry.name) === firstBaseName;
899
+ });
900
+ // Check if the base name is empty (array elements without explicit names)
901
+ const hasEmptyBaseName = !firstBaseName || firstBaseName === '';
902
+ const isArray = hasEmptyBaseName || allSameName;
903
+ if (isArray) {
904
+ // FlowArray: reconstruct array of elements
905
+ const result = [];
906
+ for (const child of children) {
907
+ const childEntry = child;
908
+ if (childEntry.children && childEntry.children.length > 0) {
909
+ // Nested object or array - get corresponding complexObject data for this element
910
+ let elementComplexData;
911
+ if (Array.isArray(complexObjectData) && result.length < complexObjectData.length) {
912
+ elementComplexData = complexObjectData[result.length];
913
+ }
914
+ result.push(parseChildrenArray(childEntry.children, undefined, undefined, elementComplexData, labelCacheMap));
915
+ }
916
+ else if (childEntry.value !== undefined && childEntry.value !== null && childEntry.value !== '') {
917
+ // Primitive value - convert to proper type
918
+ // Use parameter type if available, otherwise use passed elementType
919
+ const uiType = childEntry.parameter?.type || elementType;
920
+ const convertedValue = typeof childEntry.value === 'string'
921
+ ? convertChildValueToType(childEntry.value, uiType, labelCacheMap)
922
+ : childEntry.value;
923
+ result.push(convertedValue);
924
+ }
925
+ else if (Array.isArray(complexObjectData) && result.length < complexObjectData.length) {
926
+ // Value is empty/null, try to get from complexObject
927
+ result.push(complexObjectData[result.length]);
928
+ }
929
+ }
930
+ return result;
931
+ }
932
+ else {
933
+ // FlowObject: reconstruct object with named fields
934
+ const result = {};
935
+ for (const child of children) {
936
+ const childEntry = child;
937
+ if (!childEntry.name) {
938
+ continue;
939
+ }
940
+ // Strip parent prefix from field name (e.g., "project.name" -> "name")
941
+ // This is needed for assignSubflowOutputs where names are prefixed with parent
942
+ const fieldName = getBaseName(childEntry.name);
943
+ if (childEntry.children && childEntry.children.length > 0) {
944
+ // Nested object or array
945
+ // Extract element type from parameter.type if this is an array (e.g., "array.integer" -> "integer")
946
+ const childElementType = extractArrayElementType(childEntry.parameter?.type);
947
+ // Extract nested complex object data for this field
948
+ let nestedComplexData;
949
+ if (complexObjectData &&
950
+ typeof complexObjectData === 'object' &&
951
+ !Array.isArray(complexObjectData)) {
952
+ const objData = complexObjectData;
953
+ nestedComplexData = objData[fieldName];
954
+ }
955
+ // Extract type schema for this nested child
956
+ // Try to get schema from the child entry itself, or fall back to parent's type map
957
+ const childTypeMap = extractNestedTypeSchema(childEntry) || nestedTypeMap;
958
+ result[fieldName] = parseChildrenArray(childEntry.children, childElementType, childTypeMap, nestedComplexData, labelCacheMap);
959
+ }
960
+ else if (childEntry.value !== undefined && childEntry.value !== null && childEntry.value !== '') {
961
+ // Primitive value - convert to proper type
962
+ // Try parameter type first, then nested type map, then no type
963
+ const uiType = childEntry.parameter?.type || nestedTypeMap?.get(childEntry.name);
964
+ const convertedValue = typeof childEntry.value === 'string'
965
+ ? convertChildValueToType(childEntry.value, uiType, labelCacheMap)
966
+ : childEntry.value;
967
+ result[fieldName] = convertedValue;
968
+ }
969
+ else if (complexObjectData &&
970
+ typeof complexObjectData === 'object' &&
971
+ !Array.isArray(complexObjectData)) {
972
+ // No value in children, try to get from complexObject
973
+ const objData = complexObjectData;
974
+ if (fieldName in objData) {
975
+ const value = objData[fieldName];
976
+ // Apply type conversion if we have type information
977
+ const uiType = nestedTypeMap?.get(childEntry.name) || nestedTypeMap?.get(fieldName);
978
+ if (typeof value === 'string' && uiType) {
979
+ result[fieldName] = convertPrimitiveValue(value, uiType);
980
+ }
981
+ else {
982
+ result[fieldName] = value;
983
+ }
984
+ }
985
+ }
986
+ else if (childEntry.parameter?.type && childEntry.parameter.type.startsWith('array')) {
987
+ // Array field with no children or value - initialize as empty array
988
+ result[fieldName] = [];
989
+ }
990
+ }
991
+ // Merge any fields from complexObject that aren't in children
992
+ // This handles primitive arrays that are only in complexObject
993
+ if (complexObjectData && typeof complexObjectData === 'object' && !Array.isArray(complexObjectData)) {
994
+ const objData = complexObjectData;
995
+ for (const key of Object.keys(objData)) {
996
+ if (!(key in result)) {
997
+ result[key] = objData[key];
998
+ }
999
+ }
1000
+ }
1001
+ return result;
1002
+ }
1003
+ }
1004
+ /**
1005
+ * Extracts plain values from ServiceNow's $cv wrapped format.
1006
+ */
1007
+ function extractComplexObjectValues(complexObject) {
1008
+ if (typeof complexObject !== 'object' || complexObject === null) {
1009
+ return complexObject;
1010
+ }
1011
+ const obj = complexObject;
1012
+ if (obj.$cv && '$v' in obj.$cv) {
1013
+ return obj.$cv.$v;
1014
+ }
1015
+ if (obj.$COCollectionField) {
1016
+ return extractComplexObjectValues(obj.$COCollectionField);
1017
+ }
1018
+ if (Array.isArray(complexObject)) {
1019
+ return complexObject.map((item) => extractComplexObjectValues(item));
1020
+ }
1021
+ const result = {};
1022
+ for (const [key, value] of Object.entries(complexObject)) {
1023
+ if (key === 'name$' || key === '$COCollectionField') {
1024
+ continue;
1025
+ }
1026
+ result[key] = extractComplexObjectValues(value);
1027
+ }
1028
+ return result;
1029
+ }
1030
+ /**
1031
+ * Reconstructs FlowObject/FlowArray from complexObjectSchema with mapped datapills.
1032
+ * This handles the UI format where children array is empty but datapills are stored in facets.
1033
+ */
1034
+ function reconstructFromMappedFacets(schema, complexObject) {
1035
+ if (typeof schema !== 'object' || schema === null) {
1036
+ return null;
1037
+ }
1038
+ const schemaObj = schema;
1039
+ const typeKey = Object.keys(schemaObj).find((k) => k.startsWith('FlowDesigner:'));
1040
+ if (!typeKey) {
1041
+ return null;
1042
+ }
1043
+ const template = schemaObj[typeKey];
1044
+ if (typeof template !== 'object' || template === null) {
1045
+ return null;
1046
+ }
1047
+ const templateObj = template;
1048
+ const literalValues = extractComplexObjectValues(complexObject);
1049
+ const mappings = extractMappingsFromFacets(templateObj);
1050
+ if (mappings.size === 0) {
1051
+ return literalValues;
1052
+ }
1053
+ return applyMappingsToValues(literalValues, mappings);
1054
+ }
1055
+ /**
1056
+ * Extracts datapill mappings from field facets in the schema template.
1057
+ * Recursively searches through nested objects and arrays to find all $field_facets.
1058
+ */
1059
+ function extractMappingsFromFacets(template) {
1060
+ const mappings = new Map();
1061
+ function extractFromObject(obj) {
1062
+ if (typeof obj !== 'object' || obj === null) {
1063
+ return;
1064
+ }
1065
+ if (Array.isArray(obj)) {
1066
+ for (const item of obj) {
1067
+ extractFromObject(item);
1068
+ }
1069
+ return;
1070
+ }
1071
+ const objMap = obj;
1072
+ for (const key of Object.keys(objMap)) {
1073
+ if (key.endsWith('.$field_facets')) {
1074
+ const facets = objMap[key];
1075
+ if (typeof facets !== 'object' || facets === null) {
1076
+ continue;
1077
+ }
1078
+ const facetsObj = facets;
1079
+ const simpleMapFacetStr = facetsObj.SimpleMapFacet;
1080
+ if (typeof simpleMapFacetStr === 'string') {
1081
+ try {
1082
+ const facetObj = JSON.parse(simpleMapFacetStr);
1083
+ if (facetObj.mapped) {
1084
+ const mappedObj = JSON.parse(facetObj.mapped);
1085
+ for (const [path, datapill] of Object.entries(mappedObj)) {
1086
+ mappings.set(path, stripDatapillTypeAnnotation(datapill));
1087
+ }
1088
+ }
1089
+ }
1090
+ catch {
1091
+ // Skip invalid facets
1092
+ }
1093
+ }
1094
+ }
1095
+ else {
1096
+ // Recursively search nested objects
1097
+ extractFromObject(objMap[key]);
1098
+ }
1099
+ }
1100
+ }
1101
+ extractFromObject(template);
1102
+ return mappings;
1103
+ }
1104
+ /**
1105
+ * Applies datapill mappings to literal values by setting values at dotted paths.
1106
+ */
1107
+ function applyMappingsToValues(values, mappings) {
1108
+ const result = JSON.parse(JSON.stringify(values));
1109
+ for (const [path, datapill] of mappings.entries()) {
1110
+ setValueAtPath(result, path, datapill);
1111
+ }
1112
+ return result;
1113
+ }
1114
+ /**
1115
+ * Sets a value at a dotted path in an object/array structure.
1116
+ * Handles array indices like "tasks[0].dueDate".
1117
+ */
1118
+ function setValueAtPath(obj, path, value) {
1119
+ const parts = path.split(/\.|\[|\]/).filter((p) => p !== '');
1120
+ let current = obj;
1121
+ for (let i = 0; i < parts.length - 1; i++) {
1122
+ const part = parts[i];
1123
+ if (!part) {
1124
+ continue;
1125
+ }
1126
+ const nextPart = parts[i + 1];
1127
+ if (nextPart && /^\d+$/.test(nextPart)) {
1128
+ if (Array.isArray(current)) {
1129
+ const idx = Number.parseInt(part, 10);
1130
+ if (!current[idx]) {
1131
+ current[idx] = {};
1132
+ }
1133
+ current = current[idx];
1134
+ }
1135
+ else {
1136
+ if (!Array.isArray(current[part])) {
1137
+ current[part] = [];
1138
+ }
1139
+ current = current[part];
1140
+ }
1141
+ }
1142
+ else if (/^\d+$/.test(part)) {
1143
+ const idx = Number.parseInt(part, 10);
1144
+ if (Array.isArray(current)) {
1145
+ if (!current[idx]) {
1146
+ current[idx] = {};
1147
+ }
1148
+ current = current[idx];
1149
+ }
1150
+ }
1151
+ else {
1152
+ if (Array.isArray(current)) {
1153
+ const idx = Number.parseInt(part, 10);
1154
+ if (!current[idx]) {
1155
+ current[idx] = {};
1156
+ }
1157
+ current = current[idx];
1158
+ }
1159
+ else {
1160
+ if (typeof current[part] !== 'object' || current[part] === null) {
1161
+ current[part] = {};
1162
+ }
1163
+ current = current[part];
1164
+ }
1165
+ }
1166
+ }
1167
+ const lastPart = parts[parts.length - 1];
1168
+ if (lastPart) {
1169
+ if (/^\d+$/.test(lastPart)) {
1170
+ const idx = Number.parseInt(lastPart, 10);
1171
+ if (Array.isArray(current)) {
1172
+ current[idx] = value;
1173
+ }
1174
+ }
1175
+ else {
1176
+ if (!Array.isArray(current)) {
1177
+ current[lastPart] = value;
1178
+ }
1179
+ }
1180
+ }
1181
+ }
1182
+ /**
1183
+ * Generic helper to parse an array of entries with name-value pairs into an object.
1184
+ * Converts string values to appropriate types using type information from the schema.
1185
+ *
1186
+ * **Inline Script Support:**
1187
+ * Detects entries with `scriptActive: true` and creates FDInlineScriptCallShape objects
1188
+ * that represent `wfa.inlineScript('...')` calls in the generated Fluent code.
1189
+ *
1190
+ * **FlowObject/FlowArray Support:**
1191
+ * Detects entries with non-empty `children` arrays and recursively parses them back
1192
+ * into nested objects or arrays, reversing the buildChildrenArray operation.
1193
+ *
1194
+ * @param entries - Array of entries with name, value, and optional scriptActive/script properties
1195
+ * @param typeMap - Optional map of names to their internal types for proper type conversion
1196
+ * @param record - Optional source Record for creating FDInlineScriptCallShape with proper source
1197
+ * @returns Object with names as keys and properly typed values or FDInlineScriptCallShape for inline scripts
1198
+ */
1199
+ function parseEntriesFromArray(entries, typeMap, labelCacheMap) {
1200
+ const result = {};
1201
+ for (const entry of entries) {
1202
+ if (!entry.name) {
1203
+ continue;
1204
+ }
1205
+ // Check if this is an inline script (matches flow-instance-plugin.ts pattern)
1206
+ // Return script metadata that buildVariableOrOutputArguments will recognize
1207
+ if (entry.scriptActive === true && entry.script) {
1208
+ const scriptData = entry.script[entry.name];
1209
+ if (scriptData?.script) {
1210
+ // Return metadata object (not a Shape) so it can be processed later
1211
+ result[entry.name] = {
1212
+ scriptActive: true,
1213
+ scriptContent: scriptData.script,
1214
+ };
1215
+ continue;
1216
+ }
1217
+ }
1218
+ // Check if this entry has children (FlowObject/FlowArray)
1219
+ if (entry.children && Array.isArray(entry.children) && entry.children.length > 0) {
1220
+ // Special case: empty arrays are represented as a single child with empty string value
1221
+ // Empty arrays have: no name, empty string value, and undefined children (not empty array)
1222
+ // Arrays with objects (like [{item: ''}]) have children with names and/or children arrays
1223
+ const firstChild = entry.children[0];
1224
+ const isEmptyArray = entry.children.length === 1 &&
1225
+ firstChild.value === '' &&
1226
+ !firstChild.name && // Empty arrays have no name on the child element
1227
+ firstChild.children === undefined; // Empty arrays have undefined children, not empty array
1228
+ if (isEmptyArray) {
1229
+ result[entry.name] = [];
1230
+ continue;
1231
+ }
1232
+ // If parent value is a datapill (pure or template expression), use it directly and ignore children
1233
+ // This handles the case where a datapill is assigned to a FlowObject variable
1234
+ // Check for datapills: starts with {{ (pure datapill) or contains {{ but not starting with { (template expression)
1235
+ const isDatapillValue = entry.value &&
1236
+ typeof entry.value === 'string' &&
1237
+ (entry.value.startsWith('{{') ||
1238
+ (entry.value.includes('{{') && entry.value.includes('}}') && !entry.value.startsWith('{')));
1239
+ if (isDatapillValue) {
1240
+ const uiType = typeMap?.get(entry.name);
1241
+ const convertedValue = convertChildValueToType(entry.value, uiType, labelCacheMap);
1242
+ result[entry.name] = convertedValue;
1243
+ continue;
1244
+ }
1245
+ // Try to extract actual values from complexObject field if available
1246
+ if (entry.value && typeof entry.value === 'string' && !childrenContainDatapills(entry.children)) {
1247
+ try {
1248
+ const parsed = JSON.parse(entry.value);
1249
+ if (parsed.complexObject) {
1250
+ const extractedValue = extractComplexObjectValues(parsed.complexObject);
1251
+ // Apply type conversion using schema information
1252
+ const nestedTypeMap = extractNestedTypeSchema(entry);
1253
+ if (nestedTypeMap &&
1254
+ typeof extractedValue === 'object' &&
1255
+ extractedValue !== null &&
1256
+ !Array.isArray(extractedValue)) {
1257
+ // For FlowObject, apply type conversion to each field (including nested objects)
1258
+ result[entry.name] = applyTypeConversionToObject(extractedValue, nestedTypeMap);
1259
+ }
1260
+ else {
1261
+ result[entry.name] = extractedValue;
1262
+ }
1263
+ continue;
1264
+ }
1265
+ }
1266
+ catch {
1267
+ // Fall through to children parsing
1268
+ }
1269
+ }
1270
+ // Fallback: Parse structure from children array
1271
+ // Extract complexObject data if available for merging with children
1272
+ let complexObjData;
1273
+ if (entry.value && typeof entry.value === 'string') {
1274
+ try {
1275
+ const parsed = JSON.parse(entry.value);
1276
+ if (parsed.complexObject) {
1277
+ complexObjData = extractComplexObjectValues(parsed.complexObject);
1278
+ }
1279
+ }
1280
+ catch {
1281
+ // Ignore parse errors
1282
+ }
1283
+ }
1284
+ const elementType = getArrayElementType(entry);
1285
+ const nestedTypeMap = extractNestedTypeSchema(entry);
1286
+ const parsedValue = parseChildrenArray(entry.children, elementType, nestedTypeMap, complexObjData, labelCacheMap);
1287
+ result[entry.name] = parsedValue;
1288
+ continue;
1289
+ }
1290
+ // Handle UI format: children empty but complexObjectSchema has mapped datapills in facets
1291
+ if (entry.value && typeof entry.value === 'string') {
1292
+ try {
1293
+ const parsed = JSON.parse(entry.value);
1294
+ if (parsed.complexObjectSchema && parsed.complexObject) {
1295
+ // Extract datapills from mapped facets and merge with literal values
1296
+ const reconstructed = reconstructFromMappedFacets(parsed.complexObjectSchema, parsed.complexObject);
1297
+ if (reconstructed !== null) {
1298
+ result[entry.name] = reconstructed;
1299
+ continue;
1300
+ }
1301
+ }
1302
+ }
1303
+ catch {
1304
+ // Fall through to regular value handling
1305
+ }
1306
+ }
1307
+ // Handle regular values (non-inline-script)
1308
+ if (entry.value !== undefined && entry.value !== null) {
1309
+ // Get the type for this entry from the schema
1310
+ const uiType = typeMap?.get(entry.name);
1311
+ // Strip type annotation from datapill strings before normalization
1312
+ // ServiceNow stores datapills with type annotations like {{trigger.name|string}}
1313
+ const valueStr = String(entry.value);
1314
+ const cleanedValue = stripDatapillTypeAnnotation(valueStr);
1315
+ // Use normalizeInputValue to handle type conversion
1316
+ // This converts:
1317
+ // - "true"/"false" → boolean (when uiType is 'boolean')
1318
+ // - "1"/"0" → true/false (when uiType is 'boolean')
1319
+ // - "123" → number
1320
+ // - JSON strings → parsed objects
1321
+ // - Datapills like "{{trigger.name}}" → kept as string (for later conversion)
1322
+ const normalizedValue = (0, flow_instance_plugin_1.normalizeInputValue)(cleanedValue, uiType);
1323
+ result[entry.name] = normalizedValue;
1324
+ }
1325
+ }
1326
+ return result;
1327
+ }
1328
+ })(FlowLogicValueProcessor || (FlowLogicValueProcessor = {}));
1329
+ /**
1330
+ * Helper function to check if children array contains any datapill values.
1331
+ * Datapills are indicated by {{...}} syntax in the value field.
1332
+ *
1333
+ * @param children - The children array to check
1334
+ * @returns true if any child has a datapill value
1335
+ */
1336
+ function childrenContainDatapills(children) {
1337
+ for (const child of children) {
1338
+ if (typeof child === 'object' && child !== null) {
1339
+ const childObj = child;
1340
+ // Check if this child has a datapill value (pure datapill or template expression)
1341
+ if (childObj.value && typeof childObj.value === 'string') {
1342
+ // Check for pure datapill or template expression containing datapills
1343
+ if (childObj.value.includes('{{') && childObj.value.includes('}}')) {
1344
+ return true;
1345
+ }
1346
+ }
1347
+ // Recursively check nested children
1348
+ if (childObj.children && Array.isArray(childObj.children) && childObj.children.length > 0) {
1349
+ if (childrenContainDatapills(childObj.children)) {
1350
+ return true;
1351
+ }
1352
+ }
1353
+ }
1354
+ }
1355
+ return false;
1356
+ }
1357
+ // Type guard functions for each shape type
1358
+ function isConditionalLogicShape(expr) {
1359
+ return [flow_logic_constants_1.FLOW_LOGIC.IF, flow_logic_constants_1.FLOW_LOGIC.ELSEIF, flow_logic_constants_1.FLOW_LOGIC.ELSE].includes(expr.getCallee());
1360
+ }
1361
+ function isForEachShape(expr) {
1362
+ return expr.getCallee() === flow_logic_constants_1.FLOW_LOGIC.FOR_EACH;
1363
+ }
1364
+ function isGoBackToShape(expr) {
1365
+ return expr.getCallee() === flow_logic_constants_1.FLOW_LOGIC.GOBACKTO;
1366
+ }
1367
+ function isTryCatchShape(expr) {
1368
+ return expr.getCallee() === flow_logic_constants_1.FLOW_LOGIC.TRY_CATCH;
1369
+ }
1370
+ function isDoInParallelShape(expr) {
1371
+ return expr.getCallee() === flow_logic_constants_1.FLOW_LOGIC.DO_IN_PARALLEL;
1372
+ }
1373
+ function isSetFlowVariablesShape(expr) {
1374
+ return expr.getCallee() === flow_logic_constants_1.FLOW_LOGIC.SET_FLOW_VARIABLES;
1375
+ }
1376
+ function isAssignSubflowOutputsShape(expr) {
1377
+ return expr.getCallee() === flow_logic_constants_1.FLOW_LOGIC.ASSIGN_SUBFLOW_OUTPUTS;
1378
+ }
1379
+ /**
1380
+ * Checks if a shape is a datapill shape (PropertyAccessShape, TemplateExpressionShape, IdentifierShape, PillShape, or PillTemplateShape)
1381
+ */
1382
+ function isDataPillShape(shape) {
1383
+ return (shape instanceof sdk_build_core_1.PropertyAccessShape ||
1384
+ shape instanceof sdk_build_core_1.TemplateExpressionShape ||
1385
+ shape instanceof sdk_build_core_1.IdentifierShape ||
1386
+ shape instanceof data_pill_shapes_1.PillShape ||
1387
+ shape instanceof data_pill_shapes_1.PillTemplateShape);
1388
+ }
1389
+ /**
1390
+ * Recursively resolves datapills in nested values (for FlowObjects/FlowArrays).
1391
+ *
1392
+ * @param value - The value to resolve datapills in
1393
+ * @param transform - Transform context for shape conversion
1394
+ * @returns Resolved value with datapills replaced
1395
+ */
1396
+ async function resolveNestedDataPills(value, transform) {
1397
+ // Handle datapill shapes
1398
+ if (value instanceof sdk_build_core_1.Shape && isDataPillShape(value)) {
1399
+ return await (0, utils_1.resolveDataPillShape)(value, transform);
1400
+ }
1401
+ // Handle ObjectShape - need to resolve its entries
1402
+ if (value instanceof sdk_build_core_1.Shape && (value.isObject() || value.is(sdk_build_core_1.DurationShape))) {
1403
+ const objectShape = value.isObject()
1404
+ ? value.asObject()
1405
+ : sdk_build_core_1.Shape.from(value.getSource(), value.as(sdk_build_core_1.DurationShape).getDuration()).asObject();
1406
+ const resolvedObj = {};
1407
+ const entries = objectShape.entries({ resolve: false });
1408
+ for (const [key, shape] of entries) {
1409
+ resolvedObj[key] = await resolveNestedDataPills(shape, transform);
1410
+ }
1411
+ return resolvedObj;
1412
+ }
1413
+ // Handle ArrayShape - need to resolve its elements
1414
+ if (value instanceof sdk_build_core_1.Shape && value.isArray()) {
1415
+ const arrayShape = value.asArray();
1416
+ const resolvedArray = [];
1417
+ // IMPORTANT: Use getElements(false) to prevent premature resolution of CallExpressionShapes
1418
+ const elements = arrayShape.getElements(false);
1419
+ for (const element of elements) {
1420
+ if (element === undefined) {
1421
+ continue;
1422
+ }
1423
+ resolvedArray.push(await resolveNestedDataPills(element, transform));
1424
+ }
1425
+ return resolvedArray;
1426
+ }
1427
+ // Handle CallExpressionShape for wfa.dataPill() - convert to pill string
1428
+ if (value instanceof sdk_build_core_1.Shape && value.is(sdk_build_core_1.CallExpressionShape)) {
1429
+ const callExpr = value.as(sdk_build_core_1.CallExpressionShape);
1430
+ if (callExpr.getCallee() === 'wfa.dataPill') {
1431
+ // The first argument is a PropertyAccessShape (e.g., params.inputs.inputString)
1432
+ // The second argument is the type hint (e.g., 'string', 'integer')
1433
+ const firstArg = callExpr.getArgument(0);
1434
+ const secondArg = callExpr.getArgument(1);
1435
+ if (firstArg && firstArg.is(sdk_build_core_1.PropertyAccessShape)) {
1436
+ // Extract the pill components from PropertyAccessShape
1437
+ const propAccess = firstArg.as(sdk_build_core_1.PropertyAccessShape);
1438
+ const elements = propAccess.getElements();
1439
+ if (elements.length >= 2) {
1440
+ const propertyNames = [];
1441
+ elements.forEach((element) => {
1442
+ if (element.is(sdk_build_core_1.IdentifierShape)) {
1443
+ propertyNames.push(element.as(sdk_build_core_1.IdentifierShape).getName());
1444
+ }
1445
+ });
1446
+ // Use the same logic as DataPillPlugin to determine root identifier and path
1447
+ const { rootIdentifier, pathStr } = (0, flow_data_pill_plugin_1.determineRootIdentifierAndPath)(propertyNames,
1448
+ // We don't have diagnostics here, casting through unknown to satisfy the type
1449
+ // The function will return null values if this object is used
1450
+ {}, propAccess);
1451
+ // Get type hint if provided
1452
+ let typePart = '';
1453
+ if (secondArg && secondArg.isString()) {
1454
+ const typeHint = secondArg.asString().getValue();
1455
+ typePart = `|${typeHint}`;
1456
+ }
1457
+ // Return pill format: {{rootIdentifier.path|type}}
1458
+ if (rootIdentifier) {
1459
+ return pathStr
1460
+ ? `{{${rootIdentifier}.${pathStr}${typePart}}}`
1461
+ : `{{${rootIdentifier}${typePart}}}`;
1462
+ }
1463
+ }
1464
+ }
1465
+ // If already converted to PillShape or try normal resolution
1466
+ if (firstArg && isDataPillShape(firstArg)) {
1467
+ return await (0, utils_1.resolveDataPillShape)(firstArg, transform);
1468
+ }
1469
+ }
1470
+ }
1471
+ // Extract value from other Shape types
1472
+ if (value instanceof sdk_build_core_1.Shape) {
1473
+ value = value.getValue();
1474
+ }
1475
+ // Recursively handle arrays
1476
+ if (Array.isArray(value)) {
1477
+ const resolvedArray = [];
1478
+ for (const element of value) {
1479
+ // Skip undefined elements
1480
+ if (element === undefined) {
1481
+ continue;
1482
+ }
1483
+ resolvedArray.push(await resolveNestedDataPills(element, transform));
1484
+ }
1485
+ return resolvedArray;
1486
+ }
1487
+ // Recursively handle objects
1488
+ if (typeof value === 'object' && value !== null) {
1489
+ const resolvedObj = {};
1490
+ for (const [key, val] of Object.entries(value)) {
1491
+ // Skip undefined values
1492
+ if (val === undefined) {
1493
+ continue;
1494
+ }
1495
+ resolvedObj[key] = await resolveNestedDataPills(val, transform);
1496
+ }
1497
+ return resolvedObj;
1498
+ }
1499
+ // Return primitive values as-is
1500
+ return value;
1501
+ }
1502
+ /**
1503
+ * Processes inline scripts in flow logic values (setFlowVariables, assignSubflowOutputs).
1504
+ * Follows the same pattern as checkAndResolveInlineScripts() in flow-instance-plugin.ts.
1505
+ *
1506
+ * @param config - The ObjectShape containing config properties
1507
+ * @returns Array of [key, value] tuples where inline scripts are serialized
1508
+ */
1509
+ function processInlineScriptsInFlowLogic(config) {
1510
+ const entries = config.entries({ resolve: false });
1511
+ const results = [];
1512
+ for (const [key, shape] of entries) {
1513
+ // Handle wfa.inlineScript() calls
1514
+ if (shape instanceof inline_script_plugin_1.FDInlineScriptCallShape) {
1515
+ const scriptContent = shape.getScriptContent();
1516
+ // Wrap in TemplateExpressionShape for proper serialization
1517
+ const templateShape = new sdk_build_core_1.TemplateExpressionShape({
1518
+ source: shape,
1519
+ literalText: scriptContent,
1520
+ });
1521
+ // Create InlineScriptShape for Flow Designer serialization
1522
+ const inlineScript = new flow_shapes_1.InlineScriptShape({
1523
+ source: templateShape,
1524
+ scriptContent,
1525
+ });
1526
+ // Convert to Flow Designer JSON format
1527
+ const scriptValue = inlineScript.toFlowDesignerJson(key);
1528
+ results.push([key, scriptValue]);
1529
+ }
1530
+ }
1531
+ return results;
1532
+ }
1533
+ /**
1534
+ * Resolves datapills and inline scripts in flow logic config properties.
1535
+ * Similar to prepareActionInstanceValueJson() in flow-instance-plugin.ts.
1536
+ *
1537
+ * @param config - The ObjectShape containing config properties
1538
+ * @param transform - Transform context for shape conversion
1539
+ * @param diagnostics - Diagnostics for reporting errors
1540
+ * @returns ObjectShape with resolved datapill and inline script values
1541
+ */
1542
+ async function resolveConfigDataPills(config, transform, diagnostics) {
1543
+ const entries = config.entries({ resolve: false });
1544
+ const dataPillProps = {};
1545
+ // Step 1: Resolve datapills (including nested datapills in FlowObject/FlowArray values)
1546
+ for (const [key, shape] of entries) {
1547
+ // Validate: annotation field must not contain datapills or inline scripts
1548
+ if (key === 'annotation' && (isDataPillShape(shape) || shape instanceof inline_script_plugin_1.FDInlineScriptCallShape)) {
1549
+ diagnostics.error(shape, 'Datapills and inline scripts are not allowed in the annotation field. Please use a static string value.');
1550
+ // Still extract the value to continue processing
1551
+ dataPillProps[key] = shape.getValue();
1552
+ continue;
1553
+ }
1554
+ if (isDataPillShape(shape)) {
1555
+ dataPillProps[key] = await (0, utils_1.resolveDataPillShape)(shape, transform);
1556
+ }
1557
+ else {
1558
+ // Recursively resolve nested datapills in FlowObject/FlowArray values
1559
+ dataPillProps[key] = await resolveNestedDataPills(shape, transform);
1560
+ }
1561
+ }
1562
+ // Step 2: Process inline scripts (wfa.inlineScript() calls)
1563
+ // This serializes inline scripts into Flow Designer JSON format with scriptActive: true
1564
+ const inlineScriptResults = processInlineScriptsInFlowLogic(config);
1565
+ const inlineScriptMap = new Map(inlineScriptResults);
1566
+ // Step 3: Replace raw inline script strings with their serialized JSON objects
1567
+ // For fields with inline scripts: replace the raw string from Step 1 with the properly
1568
+ // serialized Flow Designer JSON object from Step 2. All other fields remain unchanged.
1569
+ const mergedProps = {};
1570
+ for (const [key, value] of Object.entries(dataPillProps)) {
1571
+ mergedProps[key] = inlineScriptMap.has(key) ? inlineScriptMap.get(key) : value;
1572
+ }
1573
+ return sdk_build_core_1.Shape.from(config.getSource(), mergedProps).asObject();
1574
+ }
1575
+ /**
1576
+ * Extracts the appropriate data from different flow logic shape types.
1577
+ * Resolves datapills in config properties for If, ElseIf, Else, ForEach, and WaitForADuration.
1578
+ */
1579
+ async function extractDataFromShape(expr, transform, diagnostics) {
1580
+ // Use a more elegant approach with early returns for each shape type
1581
+ if (isGoBackToShape(expr)) {
1582
+ return expr.getStep();
1583
+ }
1584
+ if (isSetFlowVariablesShape(expr)) {
1585
+ const variablesToSet = expr.getVariablesToSet();
1586
+ return await resolveConfigDataPills(variablesToSet, transform, diagnostics);
1587
+ }
1588
+ if (isAssignSubflowOutputsShape(expr)) {
1589
+ const assignedSubflowOutputs = expr.getAssignedSubflowOutputs();
1590
+ return await resolveConfigDataPills(assignedSubflowOutputs, transform, diagnostics);
1591
+ }
1592
+ if (isForEachShape(expr)) {
1593
+ // Check if argument 0 (items) is a PropertyAccessShape before processing
1594
+ const itemsArg = expr.getArgument(0, false);
1595
+ if (itemsArg?.is(sdk_build_core_1.PropertyAccessShape)) {
1596
+ const items = expr.getItems();
1597
+ const itemString = await (0, utils_1.resolveDataPillShape)(items, transform);
1598
+ return sdk_build_core_1.Shape.from(expr, itemString).asString();
1599
+ }
1600
+ // If not a PropertyAccessShape (e.g., StringLiteralShape when no data pill assigned),
1601
+ // return empty string instead of falling through to default case (which returns ObjectShape)
1602
+ return sdk_build_core_1.Shape.from(expr, '').asString();
1603
+ }
1604
+ // For conditional logic (If/ElseIf/Else) and WAIT_FOR_A_DURATION, resolve datapills in config
1605
+ const logicType = expr.getCallee();
1606
+ if (isConditionalLogicShape(expr) || logicType === flow_logic_constants_1.FLOW_LOGIC.WAIT_FOR_A_DURATION) {
1607
+ const config = expr.getConfig();
1608
+ return await resolveConfigDataPills(config, transform, diagnostics);
1609
+ }
1610
+ // Default case: extract config as-is for other shape types
1611
+ return expr.getConfig();
1612
+ }
1613
+ /**
1614
+ * Main function to process flow logic instances and build records
1615
+ */
1616
+ async function getFlowLogicInstanceRecord(expr, context) {
1617
+ const { diagnostics, transform, factory } = context;
1618
+ const logicType = expr.getCallee();
1619
+ // Validate flow logic context
1620
+ const diagnosticError = (0, flow_logic_diagnostics_1.validateFlowLogic)(expr, diagnostics);
1621
+ if (diagnosticError) {
1622
+ diagnostics.error(expr, diagnosticError);
1623
+ return { success: false };
1624
+ }
1625
+ // Extract data based on shape type using type-specific extractors
1626
+ const data = await extractDataFromShape(expr, transform, diagnostics);
1627
+ // Note: childName for arrays is now handled in resolveComplexInput within postProcess functions
1628
+ const values = FlowLogicValueProcessor.prepare(logicType, data);
1629
+ let instanceRecord = await buildFlowLogicInstanceRecord(expr, factory, values);
1630
+ if (isAssignSubflowOutputsShape(expr)) {
1631
+ instanceRecord = instanceRecord.merge({
1632
+ outputs_assigned: expr.getAssignedSubflowOutputsAsString(),
1633
+ });
1634
+ }
1635
+ if (isSetFlowVariablesShape(expr)) {
1636
+ instanceRecord = instanceRecord.merge({
1637
+ flow_variables_assigned: expr.getVariablesToSetAsString(),
1638
+ });
1639
+ }
1640
+ instanceRecord = instanceRecord.merge({
1641
+ values: values,
1642
+ });
1643
+ // Handle sibling connections for conditional logic types
1644
+ if (requiresSiblingValidation(logicType)) {
1645
+ const siblingResult = await handleSiblingConnection(expr, transform, diagnostics);
1646
+ if (!siblingResult.success) {
1647
+ return siblingResult;
1648
+ }
1649
+ if (siblingResult.value.connectedTo) {
1650
+ instanceRecord = instanceRecord.merge({
1651
+ connected_to: siblingResult.value.connectedTo,
1652
+ values: values,
1653
+ });
1654
+ }
1655
+ }
1656
+ return { success: true, value: instanceRecord };
1657
+ }
1658
+ function requiresSiblingValidation(logicType) {
1659
+ return [flow_logic_constants_1.FLOW_LOGIC.IF, flow_logic_constants_1.FLOW_LOGIC.ELSEIF, flow_logic_constants_1.FLOW_LOGIC.ELSE].includes(logicType);
1660
+ }
1661
+ async function handleSiblingConnection(expr, transform, diagnostics) {
1662
+ const sibling = expr
1663
+ .getOriginalNode()
1664
+ .getParent()
1665
+ ?.getPreviousSibling((node) => !sdk_build_core_1.ts.Node.isCommentStatement(node))
1666
+ ?.asKind(sdk_build_core_1.ts.SyntaxKind.ExpressionStatement)
1667
+ ?.getExpression()
1668
+ .asKind(sdk_build_core_1.ts.SyntaxKind.CallExpression);
1669
+ const siblingError = (0, flow_logic_diagnostics_1.validateSibling)(expr, sibling);
1670
+ if (siblingError) {
1671
+ diagnostics.error(expr, siblingError);
1672
+ return { success: false };
1673
+ }
1674
+ const logicType = expr.getCallee();
1675
+ if (sibling && (logicType === flow_logic_constants_1.FLOW_LOGIC.ELSE || logicType === flow_logic_constants_1.FLOW_LOGIC.ELSEIF)) {
1676
+ const siblingRecord = await transform.toRecord(sibling);
1677
+ if (siblingRecord.success) {
1678
+ return { success: true, value: { connectedTo: siblingRecord.value.get('ui_id').asString().getValue() } };
1679
+ }
1680
+ }
1681
+ return { success: true, value: {} };
1682
+ }
1683
+ const FLOW_LOGIC_ARGUMENT_BUILDERS = {
1684
+ [flow_logic_constants_1.FLOW_LOGIC.GOBACKTO]: (record, _, database) => {
1685
+ const stepId = FlowLogicValueProcessor.parse(flow_logic_constants_1.FLOW_LOGIC.GOBACKTO, record.get('values').asString().getValue());
1686
+ const stepRecord = database.get('sys_hub_action_instance_v2', { ui_id: stepId, flow: record.get('flow').getValue() }) ||
1687
+ database.get('sys_hub_sub_flow_instance_v2', { ui_id: stepId, flow: record.get('flow').getValue() }) ||
1688
+ database.get('sys_hub_flow_logic_instance_v2', { ui_id: stepId, flow: record.get('flow').getValue() });
1689
+ if (!stepRecord) {
1690
+ throw new Error(`Step with id ${stepId} not found`);
1691
+ }
1692
+ // Target step validation is now handled during FlowLogicInstanceShape.toRecord phase
1693
+ // No validation needed here anymore
1694
+ const firstArg = new sdk_build_core_1.ObjectShape({
1695
+ source: record,
1696
+ properties: {
1697
+ annotation: record.get('comment').asString().getValue(),
1698
+ $id: now_id_plugin_1.NowIdShape.from(record),
1699
+ },
1700
+ });
1701
+ const source = stepRecord.getSource();
1702
+ if (source instanceof sdk_build_core_1.CallExpressionShape) {
1703
+ const identifier = stepRecord
1704
+ .getOriginalNode()
1705
+ ?.getFirstAncestorByKind(sdk_build_core_1.ts.SyntaxKind.VariableDeclaration)
1706
+ ?.getNameNode();
1707
+ if (identifier) {
1708
+ return [
1709
+ firstArg,
1710
+ new sdk_build_core_1.IdentifierShape({
1711
+ source: record,
1712
+ name: identifier.getText(),
1713
+ }),
1714
+ ];
1715
+ }
1716
+ }
1717
+ return [firstArg, sdk_build_core_1.Shape.from(record, stepId)];
1718
+ },
1719
+ [flow_logic_constants_1.FLOW_LOGIC.IF]: buildConditionalArguments,
1720
+ [flow_logic_constants_1.FLOW_LOGIC.ELSEIF]: buildConditionalArguments,
1721
+ [flow_logic_constants_1.FLOW_LOGIC.ELSE]: buildConditionalArguments,
1722
+ [flow_logic_constants_1.FLOW_LOGIC.ENDFLOW]: buildBasicArguments,
1723
+ [flow_logic_constants_1.FLOW_LOGIC.EXITLOOP]: buildBasicArguments,
1724
+ [flow_logic_constants_1.FLOW_LOGIC.SKIP_ITERATION]: buildBasicArguments,
1725
+ [flow_logic_constants_1.FLOW_LOGIC.WAIT_FOR_A_DURATION]: buildWaitForADurationArguments,
1726
+ [flow_logic_constants_1.FLOW_LOGIC.FOR_EACH]: buildForEachArguments,
1727
+ [flow_logic_constants_1.FLOW_LOGIC.DO_IN_PARALLEL]: buildBasicArguments,
1728
+ [flow_logic_constants_1.FLOW_LOGIC.TRY_CATCH]: buildBasicArguments,
1729
+ [flow_logic_constants_1.FLOW_LOGIC.SET_FLOW_VARIABLES]: buildSetFlowVariablesArguments,
1730
+ [flow_logic_constants_1.FLOW_LOGIC.ASSIGN_SUBFLOW_OUTPUTS]: buildAssignSubflowOutputsArguments,
1731
+ };
1732
+ /**
1733
+ * Generic helper to build arguments for flow logic operations that follow the pattern:
1734
+ * (config, schema, values)
1735
+ *
1736
+ * This pattern is used by SetFlowVariables and AssignSubflowOutputs.
1737
+ *
1738
+ * @param record - ServiceNow sys_hub_flow_logic_instance_v2 record
1739
+ * @param database - Database to query for type information
1740
+ * @param tableName - Table name to query for schema records (e.g., 'sys_hub_flow_variable', 'sys_hub_flow_output')
1741
+ * @param flowLogicType - Flow logic type for parsing (e.g., FLOW_LOGIC.SET_FLOW_VARIABLES)
1742
+ * @param schemaRef - Schema reference string (e.g., '{{flowVariables}}', '{{outputs}}')
1743
+ * @returns Array of three Shape arguments
1744
+ */
1745
+ function buildVariableOrOutputArguments(record, database, tableName, flowLogicType, schemaRef) {
1746
+ const comment = record.get('comment').asString().getValue();
1747
+ const valuesString = record.get('values').asString().getValue();
1748
+ const flowId = record.get('flow').asString().getValue();
1749
+ // Get flow definition and extract type information from schema
1750
+ const typeMap = new Map();
1751
+ let labelCacheMap;
1752
+ const flowRecord = database.get('sys_hub_flow', flowId);
1753
+ if (flowRecord) {
1754
+ // Get the schema records that belong to this flow
1755
+ const schemaRecords = database.query(tableName).filter((v) => v.get('model').getValue() === flowId);
1756
+ for (const schemaRecord of schemaRecords) {
1757
+ const name = schemaRecord.get('element').asString().getValue();
1758
+ const internalType = schemaRecord.get('internal_type').asString().getValue();
1759
+ typeMap.set(name, internalType);
1760
+ }
1761
+ // Extract label cache from flow record for datapill type preservation
1762
+ try {
1763
+ const labelCacheValue = flowRecord.get('label_cache')?.getValue();
1764
+ if (labelCacheValue && typeof labelCacheValue === 'string') {
1765
+ // Parse label cache JSON and create name->type map
1766
+ const labelCacheEntries = JSON.parse(labelCacheValue);
1767
+ labelCacheMap = new Map();
1768
+ for (const entry of labelCacheEntries) {
1769
+ if (entry.name && entry.type) {
1770
+ labelCacheMap.set(entry.name, entry.type);
1771
+ }
1772
+ }
1773
+ }
1774
+ }
1775
+ catch {
1776
+ // If label cache extraction fails, continue without it
1777
+ labelCacheMap = undefined;
1778
+ }
1779
+ }
1780
+ // Parse the values from the gzipped string with type conversion
1781
+ // Returns object with properly typed values, inline script markers, or datapill strings
1782
+ const parsedData = FlowLogicValueProcessor.parse(flowLogicType, valuesString, typeMap, labelCacheMap);
1783
+ // Build the config object (first argument)
1784
+ const configArg = new sdk_build_core_1.ObjectShape({
1785
+ source: record,
1786
+ properties: {
1787
+ ...(comment ? { annotation: comment } : {}),
1788
+ $id: now_id_plugin_1.NowIdShape.from(record),
1789
+ },
1790
+ });
1791
+ // Second argument: schema reference ({{flowVariables}} or {{outputs}})
1792
+ // Keep as string - will be transformed to PropertyAccessShape by datapill transformer
1793
+ // The transformer will use the actual parameter name from the arrow function context
1794
+ const schemaArg = sdk_build_core_1.Shape.from(record, schemaRef);
1795
+ // Build the values object (third argument)
1796
+ // Process inline scripts and create FDInlineScriptCallShape (matching action plugin pattern)
1797
+ const valueProperties = {};
1798
+ for (const [key, value] of Object.entries(parsedData)) {
1799
+ // Check for inline script (has scriptActive and scriptContent from XML)
1800
+ if (value && typeof value === 'object' && 'scriptActive' in value && 'scriptContent' in value) {
1801
+ // Create FDInlineScriptCallShape for inline scripts (same as actions)
1802
+ const script = value;
1803
+ valueProperties[key] = new inline_script_plugin_1.FDInlineScriptCallShape({
1804
+ source: record,
1805
+ scriptContent: script.scriptContent,
1806
+ });
1807
+ }
1808
+ else {
1809
+ // Primitive value or string - convert using Shape.from()
1810
+ valueProperties[key] = sdk_build_core_1.Shape.from(record, value);
1811
+ }
1812
+ }
1813
+ const valuesArg = new sdk_build_core_1.ObjectShape({
1814
+ source: record,
1815
+ properties: valueProperties,
1816
+ });
1817
+ return [configArg, schemaArg, valuesArg];
1818
+ }
1819
+ /**
1820
+ * Builds arguments for SetFlowVariables when converting XML to Fluent.
1821
+ * Creates the three arguments required by the SetFlowVariables API:
1822
+ * 1. Config object with $id and optional annotation
1823
+ * 2. Schema reference (placeholder for params.flowVariables)
1824
+ * 3. Values object with variable assignments
1825
+ *
1826
+ * **Type Conversion Pipeline:**
1827
+ * XML (gzipped) → parse() → normalizeInputValue(with type) → typed values → Shape.from() → Shapes
1828
+ *
1829
+ * **Example:**
1830
+ * ```typescript
1831
+ * // XML: { variables: [{ name: "count", value: "123" }, { name: "active", value: "1" }] }
1832
+ * // Result: SetFlowVariables({ $id: ... }, params.flowVariables, { count: 123, active: true })
1833
+ * ```
1834
+ *
1835
+ * @param record - ServiceNow sys_hub_flow_logic_instance_v2 record
1836
+ * @param _logicBodyShapes - Unused parameter (required by FlowLogicArgumentBuilder interface)
1837
+ * @param database - Database to query for flow variable schemas
1838
+ * @returns Array of three Shape arguments for SetFlowVariables call
1839
+ */
1840
+ function buildSetFlowVariablesArguments(record, _logicBodyShapes, database) {
1841
+ return buildVariableOrOutputArguments(record, database, 'sys_hub_flow_variable', flow_logic_constants_1.FLOW_LOGIC.SET_FLOW_VARIABLES, '{{flowVariables}}');
1842
+ }
1843
+ /**
1844
+ * Builds arguments for AssignSubflowOutputs when converting XML to Fluent.
1845
+ * Creates the three arguments required by the AssignSubflowOutputs API:
1846
+ * 1. Config object with $id and optional annotation
1847
+ * 2. Schema reference (placeholder for params.outputs or subflow outputs schema)
1848
+ * 3. Values object with output assignments
1849
+ *
1850
+ * **Type Conversion Pipeline:**
1851
+ * XML (gzipped) → parse() → normalizeInputValue(with type) → typed values → Shape.from() → Shapes
1852
+ *
1853
+ * **Example:**
1854
+ * ```typescript
1855
+ * // XML: { outputsToAssign: [{ name: "result", value: "success" }, { name: "isComplete", value: "1" }] }
1856
+ * // Result: AssignSubflowOutputs({ $id: ... }, params.outputs, { result: "success", isComplete: true })
1857
+ * ```
1858
+ *
1859
+ * @param record - ServiceNow sys_hub_flow_logic_instance_v2 record
1860
+ * @param _logicBodyShapes - Unused parameter (required by FlowLogicArgumentBuilder interface)
1861
+ * @param database - Database to query for subflow output schemas
1862
+ * @returns Array of three Shape arguments for AssignSubflowOutputs call
1863
+ */
1864
+ function buildAssignSubflowOutputsArguments(record, _logicBodyShapes, database) {
1865
+ return buildVariableOrOutputArguments(record, database, 'sys_hub_flow_output', flow_logic_constants_1.FLOW_LOGIC.ASSIGN_SUBFLOW_OUTPUTS, '{{outputs}}');
1866
+ }
1867
+ function buildBasicArguments(record) {
1868
+ return [
1869
+ new sdk_build_core_1.ObjectShape({
1870
+ source: record,
1871
+ properties: {
1872
+ annotation: record.get('comment').asString().getValue(),
1873
+ $id: now_id_plugin_1.NowIdShape.from(record),
1874
+ },
1875
+ }),
1876
+ ];
1877
+ }
1878
+ function buildWaitForADurationArguments(record, _logicBodyShapes, database) {
1879
+ const zippedInputs = record.get('values').asString().getValue();
1880
+ const logicDefinitionId = record.get('logic_definition').asString().getValue();
1881
+ const logicDefinition = database.get('sys_hub_flow_logic_definition', logicDefinitionId);
1882
+ const definitionInputs = logicDefinition
1883
+ ?.flat()
1884
+ .filter((v) => v.is(sdk_build_core_1.Record) && v.getTable() === 'sys_hub_flow_logic_input');
1885
+ const inputsShape = buildInputsShapeFromZipped({
1886
+ zippedInputs,
1887
+ definitionInputs,
1888
+ record,
1889
+ });
1890
+ const comment = record.get('comment').asString().getValue();
1891
+ const uuid = record.get('ui_id').asString().getValue();
1892
+ // Get properties from inputsShape (which is now an ObjectShape)
1893
+ // Use entries({ resolve: false }) to preserve shape types (DurationShape, etc.)
1894
+ const inputProperties = inputsShape ? Object.fromEntries(inputsShape.entries({ resolve: false })) : {};
1895
+ const mergedProperties = {
1896
+ ...(comment ? { annotation: comment } : {}),
1897
+ $id: now_id_plugin_1.NowIdShape.from(record),
1898
+ ...(uuid ? { uuid } : {}),
1899
+ ...inputProperties,
1900
+ };
1901
+ const finalArg = new sdk_build_core_1.ObjectShape({
1902
+ source: record,
1903
+ properties: mergedProperties,
1904
+ });
1905
+ return [finalArg];
1906
+ }
1907
+ function buildConditionalArguments(record, logicBodyShapes) {
1908
+ const logicName = flow_logic_constants_1.FlowLogicSysId.getLogicName(record.get('logic_definition').asString().getValue());
1909
+ const valuesJson = FlowLogicValueProcessor.parse(logicName, record.get('values').asString().getValue());
1910
+ const properties = {
1911
+ ...valuesJson,
1912
+ annotation: record.get('comment').asString().getValue(),
1913
+ $id: now_id_plugin_1.NowIdShape.from(record),
1914
+ };
1915
+ const firstArg = new sdk_build_core_1.ObjectShape({ source: record, properties });
1916
+ return [
1917
+ firstArg,
1918
+ new arrow_function_plugin_1.ArrowFunctionShape({
1919
+ source: record,
1920
+ parameters: [],
1921
+ statements: logicBodyShapes,
1922
+ }),
1923
+ ];
1924
+ }
1925
+ /**
1926
+ * Builds arguments for ForEach flow logic from XML record.
1927
+ * Converts XML structure back to Fluent ForEach syntax.
1928
+ *
1929
+ * @param record - The sys_hub_flow_logic_instance_v2 record
1930
+ * @param logicBodyShapes - The child shapes that form the loop body
1931
+ * @returns Array of shapes: [items, config, body]
1932
+ *
1933
+ * @example
1934
+ * // XML with values: { items: "{{trigger.array_field}}" }
1935
+ * // Converts to: ForEach(params.trigger.array_field, { $id, annotation }, (item) => {...})
1936
+ */
1937
+ /**
1938
+ * Build arguments for forEach flow logic with intelligent parameter name preservation.
1939
+ *
1940
+ * PARAMETER NAMING STRATEGY (Priority Order):
1941
+ *
1942
+ * 1. **Original Source Extraction** (Round-Trip Preservation):
1943
+ * - For Fluent-authored flows, extracts parameter name from original AST
1944
+ * - Preserves user-chosen names: (dept), (category), (item_0), etc.
1945
+ * - Enables lossless round-trips: Fluent → XML → Fluent
1946
+ *
1947
+ * 2. **Order-Based Naming** (UI-Authored Flows):
1948
+ * - For UI-authored flows (no original source), generates item_${order}
1949
+ * - Creates predictable names: item_0, item_1, item_2
1950
+ * - Disambiguates nested forEach loops clearly
1951
+ *
1952
+ * 3. **Default Fallback** (Edge Cases):
1953
+ * - Falls back to 'item' if neither strategy succeeds
1954
+ *
1955
+ * @example Round-Trip Preservation
1956
+ * // Original Fluent code:
1957
+ * forEach(users, {...}, (dept) => {
1958
+ * forEach(categories, {...}, (category) => {
1959
+ * action(..., { msg: `${dept.name} - ${category.value}` })
1960
+ * })
1961
+ * })
1962
+ *
1963
+ * // After deploy + pull: PRESERVED!
1964
+ * forEach(users, {...}, (dept) => { // ✅ 'dept' preserved
1965
+ * forEach(categories, {...}, (category) => { // ✅ 'category' preserved
1966
+ * action(..., { msg: `${dept.name} - ${category.value}` })
1967
+ * })
1968
+ * })
1969
+ *
1970
+ * @example UI-Authored Flow
1971
+ * // Flow created in UI, pulled to Fluent:
1972
+ * forEach(users, {...}, (item_0) => { // Generated from order=0
1973
+ * forEach(categories, {...}, (item_3) => { // Generated from order=3
1974
+ * action(..., { msg: `${item_0.name} - ${item_3.value}` })
1975
+ * })
1976
+ * })
1977
+ *
1978
+ * @param record - The forEach flow logic instance record
1979
+ * @param logicBodyShapes - The shapes within the forEach body
1980
+ * @returns Array of shapes [items, config, body] for forEach arguments
1981
+ */
1982
+ /**
1983
+ * Extracts the forEach parameter name from the original source (for round-trip preservation).
1984
+ * Falls back to order-based naming for UI-authored flows, or 'item' as final fallback.
1985
+ *
1986
+ * @param record - The forEach flow logic record
1987
+ * @returns The parameter name to use in the arrow function
1988
+ */
1989
+ function extractForEachParameterName(record) {
1990
+ try {
1991
+ const originalSource = record.getOriginalSource();
1992
+ // Check if we have a valid ts.Node
1993
+ if (!sdk_build_core_1.ts.Node.isNode(originalSource)) {
1994
+ return getFallbackParameterName(record);
1995
+ }
1996
+ // For forEach: wfa.flowLogic.forEach(items, config, (param) => {...})
1997
+ // Third argument (index 2) is the arrow function
1998
+ const arrowFn = originalSource.getArguments()[2]?.asKind(sdk_build_core_1.ts.SyntaxKind.ArrowFunction);
1999
+ if (!arrowFn) {
2000
+ return getFallbackParameterName(record);
2001
+ }
2002
+ const params = arrowFn.getParameters();
2003
+ const paramName = params[0]?.getName();
2004
+ return paramName || getFallbackParameterName(record);
2005
+ }
2006
+ catch {
2007
+ // Failed to extract parameter name - using fallback
2008
+ return getFallbackParameterName(record);
2009
+ }
2010
+ }
2011
+ /**
2012
+ * Gets the fallback parameter name based on order or default.
2013
+ */
2014
+ function getFallbackParameterName(record) {
2015
+ const order = record.get('order')?.getValue();
2016
+ return order ? `item_${order}` : 'item';
2017
+ }
2018
+ function buildForEachArguments(record, logicBodyShapes) {
2019
+ // 1. Parse values field to extract items data pill string
2020
+ const logicName = flow_logic_constants_1.FlowLogicSysId.getLogicName(record.get('logic_definition').asString().getValue());
2021
+ const valuesJson = FlowLogicValueProcessor.parse(logicName, record.get('values').asString().getValue());
2022
+ // 2. Return items as raw string - will be converted by processInstanceForDatapills
2023
+ // with the correct parameter name extracted from the flow
2024
+ const itemsString = valuesJson.items || '';
2025
+ const itemsShape = sdk_build_core_1.Shape.from(record, itemsString);
2026
+ // 3. Build config ObjectShape
2027
+ const configShape = new sdk_build_core_1.ObjectShape({
2028
+ source: record,
2029
+ properties: {
2030
+ annotation: record.get('comment').asString().getValue(),
2031
+ $id: now_id_plugin_1.NowIdShape.from(record),
2032
+ },
2033
+ });
2034
+ // 4. Build body ArrowFunctionShape with parameter name extraction
2035
+ // Strategy for parameter naming (in priority order):
2036
+ // 1. Extract from original source (for round-trip preservation) - e.g., user wrote (item_0), (dept), etc.
2037
+ // 2. Use order-based naming for UI-authored flows - e.g., item_0, item_1, item_2
2038
+ // 3. Fall back to 'item' if order is unavailable
2039
+ const parameterName = extractForEachParameterName(record);
2040
+ const bodyShape = new arrow_function_plugin_1.ArrowFunctionShape({
2041
+ source: record,
2042
+ parameters: [new sdk_build_core_1.IdentifierShape({ source: record, name: parameterName })],
2043
+ statements: logicBodyShapes,
2044
+ });
2045
+ // 5. Return in correct order: [items, config, body]
2046
+ return [itemsShape, configShape, bodyShape];
2047
+ }
2048
+ function buildInputsShapeFromZipped({ zippedInputs, definitionInputs, record, }) {
2049
+ if (!zippedInputs) {
2050
+ return undefined;
2051
+ }
2052
+ // Type definition includes parameter field which contains type information from XML
2053
+ let inputsJson;
2054
+ try {
2055
+ const inputsBuffer = (0, zlib_1.gunzipSync)(Buffer.from(zippedInputs, 'base64'));
2056
+ inputsJson = JSON.parse(inputsBuffer.toString('utf8'));
2057
+ }
2058
+ catch {
2059
+ // Failed to parse zipped inputs - returning undefined
2060
+ return undefined;
2061
+ }
2062
+ const inputs = {};
2063
+ if (inputsJson.inputs) {
2064
+ const durationTypeInput = inputsJson.inputs.find((i) => i.name === 'duration_type');
2065
+ const durationType = (durationTypeInput ? (0, flow_instance_plugin_1.normalizeInputValue)(durationTypeInput.value) : '');
2066
+ const validProps = flow_logic_constants_1.DURATION_TYPE_PROPS[durationType];
2067
+ if (validProps) {
2068
+ for (const input of inputsJson.inputs) {
2069
+ const mappedName = flow_logic_constants_1.NAME_MAP[input.name] ?? input.name;
2070
+ if (validProps.has(mappedName)) {
2071
+ const defInput = definitionInputs?.find((def) => def.get('element').getValue() === input.name);
2072
+ const uiType = defInput?.get('ui_type')?.asString()?.getValue();
2073
+ // Use uiType or fallback to parameter.type (consistent with flow-instance-plugin)
2074
+ const effectiveType = uiType ?? input.parameter?.type;
2075
+ const value = (0, flow_instance_plugin_1.normalizeInputValue)(input.value, effectiveType, record);
2076
+ if (value !== '') {
2077
+ inputs[mappedName] = value;
2078
+ }
2079
+ }
2080
+ }
2081
+ }
2082
+ }
2083
+ return sdk_build_core_1.Shape.from(record, inputs).asObject();
2084
+ }
2085
+ function getFlowLogicArguments(logicName, record, logicBodyShapes, database) {
2086
+ const builder = FLOW_LOGIC_ARGUMENT_BUILDERS[logicName];
2087
+ if (!builder) {
2088
+ throw new Error(`Unsupported flow logic type for argument building: ${logicName}`);
2089
+ }
2090
+ return builder(record, logicBodyShapes, database);
2091
+ }
2092
+ //# sourceMappingURL=flow-logic-plugin-helpers.js.map