@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,591 @@
1
+ import type { FlowLogicInstanceShape, DoInParallelInstanceShape } from './flow-logic-shapes'
2
+ import {
3
+ ts,
4
+ PropertyAccessShape,
5
+ TemplateExpressionShape,
6
+ IdentifierShape,
7
+ ArrayShape,
8
+ ObjectShape,
9
+ CallExpressionShape,
10
+ type Diagnostics,
11
+ } from '@servicenow/sdk-build-core'
12
+ import { FLOW_LOGIC } from './flow-logic-constants'
13
+ import { getCallExpressionName } from '../../utils'
14
+ import { findAncestorByCalleeName } from '../utils/utils'
15
+ import { isDoInParallelShape, isSetFlowVariablesShape, isAssignSubflowOutputsShape } from './flow-logic-plugin-helpers'
16
+ import { PillShape } from '../utils/data-pill-shapes'
17
+ import { ARRAY_FLOW_DATA_TYPES, type ArrayFlowDataType } from '@servicenow/sdk-core/runtime/flow'
18
+ import { FDInlineScriptCallShape } from '../plugins/inline-script-plugin'
19
+
20
+ type FlowLogicValidator = (expr: FlowLogicInstanceShape) => string | undefined
21
+
22
+ const FLOW_LOGIC_VALIDATORS: { [K in FLOW_LOGIC]: FlowLogicValidator } = {
23
+ [FLOW_LOGIC.GOBACKTO]: validateGoBackTo,
24
+ [FLOW_LOGIC.IF]: validateIf,
25
+ [FLOW_LOGIC.ELSEIF]: validateIf,
26
+ [FLOW_LOGIC.ELSE]: validateIf,
27
+ [FLOW_LOGIC.ENDFLOW]: validateEndFlow,
28
+ [FLOW_LOGIC.EXITLOOP]: validateExitLoop,
29
+ [FLOW_LOGIC.SKIP_ITERATION]: validateSkipIteration,
30
+ [FLOW_LOGIC.WAIT_FOR_A_DURATION]: validateWaitForADuration,
31
+ [FLOW_LOGIC.FOR_EACH]: validateForEach,
32
+ [FLOW_LOGIC.DO_IN_PARALLEL]: validateDoInParallel,
33
+ [FLOW_LOGIC.TRY_CATCH]: () => undefined,
34
+ [FLOW_LOGIC.SET_FLOW_VARIABLES]: validateSetFlowVariables,
35
+ [FLOW_LOGIC.ASSIGN_SUBFLOW_OUTPUTS]: validateAssignSubflowOutputs,
36
+ }
37
+
38
+ /**
39
+ * Main validation function for flow logic instances.
40
+ * Validates placement rules and context requirements for different flow logic types.
41
+ *
42
+ * @param expr - The flow logic instance shape to validate
43
+ * @returns Error message if validation fails, undefined if valid
44
+ */
45
+ export function validateFlowLogic(expr: FlowLogicInstanceShape, diagnostics: Diagnostics): string | undefined {
46
+ const conditionType = expr.getCallee()
47
+ const node = expr.getOriginalNode()
48
+ const parent = node.getFirstAncestorByKind(ts.SyntaxKind.CallExpression)
49
+
50
+ if (!parent) {
51
+ return `'${conditionType}' can only be used inside a Flow() or Subflow() body`
52
+ }
53
+ const callExprName = getCallExpressionName(parent)
54
+
55
+ const allowedCallExprNames = ['Flow', 'Subflow', ...Object.values(FLOW_LOGIC)]
56
+
57
+ if (!allowedCallExprNames.includes(callExprName)) {
58
+ return `'${conditionType}' can only be used inside a Flow() or Subflow() body`
59
+ }
60
+
61
+ // Validate sibling relationships for ElseIf/Else BEFORE running type-specific validators
62
+ if (conditionType === FLOW_LOGIC.ELSEIF || conditionType === FLOW_LOGIC.ELSE) {
63
+ const sibling = node
64
+ .getParent()
65
+ ?.getPreviousSibling((n) => !ts.Node.isCommentStatement(n))
66
+ ?.asKind(ts.SyntaxKind.ExpressionStatement)
67
+ ?.getExpression()
68
+ .asKind(ts.SyntaxKind.CallExpression)
69
+
70
+ const siblingError = validateSibling(expr, sibling)
71
+ if (siblingError) {
72
+ return siblingError
73
+ }
74
+ }
75
+
76
+ const validator = FLOW_LOGIC_VALIDATORS[conditionType as FLOW_LOGIC]
77
+
78
+ if (!validator) {
79
+ diagnostics.error(expr, `Unsupported flow logic type for validation: ${conditionType}`)
80
+ return
81
+ }
82
+
83
+ return validator(expr)
84
+ }
85
+
86
+ function validateGoBackTo(expr: FlowLogicInstanceShape): string | undefined {
87
+ const placementError = validateGoBackToPlacement(expr)
88
+ if (placementError) {
89
+ return placementError
90
+ }
91
+ return undefined
92
+ }
93
+
94
+ /**
95
+ * Validates GoBackTo placement according to ServiceNow rules.
96
+ *
97
+ * Valid Go back to placement rules:
98
+ * - The Go back to flow logic must be within a branch of a parent flow logic block:
99
+ * - Then branch of If, Else If, or Else flow logic
100
+ * - Catch branch of Try flow logic
101
+ * - Case branch of Decision flow logic
102
+ * - The Go back to flow logic must be outside of the Error handler section
103
+ *
104
+ * @param expr - The GoBackTo flow logic instance shape
105
+ * @returns Error message if placement is invalid, undefined if valid
106
+ */
107
+ function validateGoBackToPlacement(expr: FlowLogicInstanceShape): string | undefined {
108
+ const node = expr.getOriginalNode()
109
+
110
+ // Check if GoBackTo is within a branch of a parent flow logic block
111
+ const parentLogic = findParentFlowLogic(node)
112
+ if (!parentLogic) {
113
+ return 'GoBackTo must be within a branch of a parent flow logic block (If/Else/Decision/Try/Catch)'
114
+ }
115
+
116
+ // Check if GoBackTo is outside of Error handler section
117
+ if (isWithinErrorHandler(node)) {
118
+ return 'GoBackTo must be outside of the Error handler section'
119
+ }
120
+
121
+ return undefined
122
+ }
123
+
124
+ /**
125
+ * Finds the nearest parent flow logic block (If/Else/Decision/Try/Catch/Parallel) in the AST.
126
+ * Used to validate GoBackTo placement within proper flow logic branches.
127
+ *
128
+ * @param node - The AST node to start searching from
129
+ * @returns The parent flow logic CallExpression, or undefined if not found
130
+ */
131
+ function findParentFlowLogic(node: ts.Node | undefined): ts.CallExpression | undefined {
132
+ const current = node?.getFirstAncestorByKind(ts.SyntaxKind.CallExpression)
133
+
134
+ if (!current) {
135
+ return undefined
136
+ }
137
+
138
+ const callName = getCallExpressionName(current)
139
+
140
+ if ([FLOW_LOGIC.IF, FLOW_LOGIC.ELSEIF, FLOW_LOGIC.ELSE, 'TryCatch', 'MakeADecision'].includes(callName)) {
141
+ if (callName === 'TryCatch') {
142
+ // For TryCatch, GoBackTo should only be in the catch block, not in try block
143
+ if (!isInCatchBlock(node)) {
144
+ return undefined // Invalid placement - not in catch block
145
+ }
146
+ }
147
+
148
+ return current
149
+ }
150
+
151
+ return undefined
152
+ }
153
+
154
+ /**
155
+ * Checks if a node is within the catch block of a TryCatch flow logic.
156
+ * GoBackTo is only allowed in the catch block, not in the try block.
157
+ *
158
+ * @param node - The AST node to check
159
+ * @returns True if within catch block, false otherwise
160
+ */
161
+ function isInCatchBlock(node: ts.Node | undefined): boolean {
162
+ const current = node
163
+ ?.getFirstAncestorByKind(ts.SyntaxKind.ArrowFunction)
164
+ ?.getParentIfKind(ts.SyntaxKind.PropertyAssignment)
165
+ if (current && current.getName() === 'catch') {
166
+ return true
167
+ }
168
+ return false
169
+ }
170
+
171
+ /**
172
+ * Checks if a node is within an Error handler section.
173
+ * GoBackTo flow logic must be outside of Error handler sections per ServiceNow rules.
174
+ *
175
+ * @param node - The AST node to check
176
+ * @returns True if within an Error handler, false otherwise
177
+ */
178
+ function isWithinErrorHandler(_node: ts.Node | undefined): boolean {
179
+ // TODO: Add implementation when Error handler is added in Flow
180
+ return false
181
+ }
182
+
183
+ /**
184
+ * Validates sibling relationships for conditional flow logic (If/Else/ElseIf).
185
+ * Ensures proper chaining and structure of conditional blocks.
186
+ *
187
+ * @param expr - The flow logic instance shape
188
+ * @param sibling - The sibling CallExpression to validate against
189
+ * @returns Error message if sibling relationship is invalid, undefined if valid
190
+ */
191
+ export function validateSibling(
192
+ expr: FlowLogicInstanceShape,
193
+ sibling: ts.CallExpression | undefined
194
+ ): string | undefined {
195
+ const conditionType = expr.getCallee()
196
+
197
+ const isElseClause = conditionType === FLOW_LOGIC.ELSE
198
+ const isElseIfClause = conditionType === FLOW_LOGIC.ELSEIF
199
+ const siblingName = sibling ? getCallExpressionName(sibling) : undefined
200
+
201
+ if (isElseClause || isElseIfClause) {
202
+ if (!sibling) {
203
+ return `${conditionType} clause must follow an If or ElseIf clause.`
204
+ }
205
+
206
+ const validPredecessors = [FLOW_LOGIC.IF, FLOW_LOGIC.ELSEIF]
207
+ if (!validPredecessors.includes(siblingName as FLOW_LOGIC)) {
208
+ return `${conditionType} clause must follow an If or ElseIf clause, but found ${siblingName}.`
209
+ }
210
+ }
211
+
212
+ return undefined
213
+ }
214
+ function validateIf(expr: FlowLogicInstanceShape): string | undefined {
215
+ const conditionType = expr.getCallee()
216
+
217
+ // If and ElseIf require a condition parameter, Else does not
218
+ if (conditionType === FLOW_LOGIC.IF || conditionType === FLOW_LOGIC.ELSEIF) {
219
+ const config = expr.getConfig()
220
+ const condition = config.get('condition')
221
+
222
+ if (!condition || condition.isUndefined()) {
223
+ return `${conditionType} requires a 'condition' field in the configuration object.`
224
+ }
225
+ }
226
+
227
+ return undefined
228
+ }
229
+
230
+ function validateEndFlow(expr: FlowLogicInstanceShape): string | undefined {
231
+ const placementError = validateEndFlowPlacement(expr)
232
+ if (placementError) {
233
+ return placementError
234
+ }
235
+ return undefined
236
+ }
237
+
238
+ function validateExitLoop(expr: FlowLogicInstanceShape): string | undefined {
239
+ return validateLoopPlacement(expr, 'Exit Loop')
240
+ }
241
+
242
+ function validateSkipIteration(expr: FlowLogicInstanceShape): string | undefined {
243
+ return validateLoopPlacement(expr, 'Skip Iteration')
244
+ }
245
+
246
+ function validateWaitForADuration(expr: FlowLogicInstanceShape): string | undefined {
247
+ const args = expr.getArguments()
248
+
249
+ if (args.length !== 1) {
250
+ return `Expected 2 arguments for ${expr.getCallee()}, but received ${args.length}`
251
+ }
252
+ return undefined
253
+ }
254
+
255
+ function validateForEach(expr: FlowLogicInstanceShape): string | undefined {
256
+ // Validate that forEach has the correct number of arguments
257
+ const args = expr.getArguments()
258
+ if (args.length < 2 || args.length > 3) {
259
+ return `ForEach requires 2-3 arguments (items, config, optional body), but received ${args.length}`
260
+ }
261
+
262
+ // Validate config argument
263
+ try {
264
+ expr.getSysId()
265
+ } catch (error) {
266
+ return 'ForEach: Second argument (config) must be an object with valid $id property'
267
+ }
268
+
269
+ // Validate items argument (first argument) - must be an array type
270
+ const itemsArg = expr.getArgument(0, false)
271
+ if (!itemsArg || itemsArg.isUndefined()) {
272
+ return 'ForEach: First argument (items) is required and cannot be undefined'
273
+ }
274
+
275
+ // Valid array types - imported from core package to ensure consistency
276
+
277
+ // Helper to validate type hint
278
+ const validateTypeHint = (typeHint: string): string | undefined => {
279
+ if (!ARRAY_FLOW_DATA_TYPES.includes(typeHint as ArrayFlowDataType)) {
280
+ return `ForEach requires an array type. The dataPill type '${typeHint}' is not an array type. Use array types like 'array.object', 'array.string', 'records', etc.`
281
+ }
282
+ return undefined
283
+ }
284
+
285
+ // Check if items is a PillShape (most common case - after DataPillPlugin transformation)
286
+ if (itemsArg instanceof PillShape) {
287
+ const typeHint = itemsArg.getType()
288
+ if (typeHint) {
289
+ const error = validateTypeHint(typeHint)
290
+ if (error) {
291
+ return error
292
+ }
293
+ }
294
+ }
295
+
296
+ // Check if items is a CallExpressionShape (before DataPillPlugin transformation)
297
+ if (itemsArg instanceof CallExpressionShape) {
298
+ const callee = itemsArg.getCallee()
299
+ if (callee === 'wfa.dataPill') {
300
+ const dataPillArgs = itemsArg.getArguments()
301
+ if (dataPillArgs.length >= 2 && dataPillArgs[1]?.isString()) {
302
+ const typeHint = dataPillArgs[1].asString().getValue()
303
+ const error = validateTypeHint(typeHint)
304
+ if (error) {
305
+ return error
306
+ }
307
+ }
308
+ }
309
+ }
310
+
311
+ return undefined
312
+ }
313
+
314
+ function validateDoInParallel(expr: FlowLogicInstanceShape): string | undefined {
315
+ if (isDoInParallelShape(expr)) {
316
+ const doInParallelExpr = expr as DoInParallelInstanceShape
317
+ const originalNode = doInParallelExpr.getOriginalNode()
318
+
319
+ // Check for nested DoInParallel
320
+ const parentDoInParallel = findAncestorByCalleeName(originalNode, FLOW_LOGIC.DO_IN_PARALLEL)
321
+ if (parentDoInParallel) {
322
+ return 'Nested DoInParallel calls are not allowed. DoInParallel cannot be used within another DoInParallel block.'
323
+ }
324
+ }
325
+
326
+ return undefined
327
+ }
328
+
329
+ /**
330
+ * Validates SetFlowVariables flow logic instance.
331
+ * Performs comprehensive validation of arguments, types, and structure.
332
+ *
333
+ * **Validations performed:**
334
+ * 1. Argument count: Must have exactly 3 arguments
335
+ * 2. Config object: Must contain required $id property
336
+ * 3. Schema argument: Must be params.flowVariables (schema reference)
337
+ * 4. Values object: Must be non-empty
338
+ * 5. Variable names: Cannot be empty or whitespace
339
+ * 6. Variable values: Must be valid types (string, number, boolean, or datapill)
340
+ *
341
+ * **Valid value types:**
342
+ * - String literals: "hello"
343
+ * - Numbers: 42, 3.14
344
+ * - Booleans: true, false
345
+ * - Objects: { a: "value", b: 42 } (ObjectShape - for FlowObject types)
346
+ * - Arrays: [1, 2, 3] (ArrayShape - for FlowArray types)
347
+ * - Datapills: params.trigger.name, params.complexObject (PropertyAccessShape)
348
+ * - Template expressions: `Hello ${params.trigger.name}` (TemplateExpressionShape)
349
+ *
350
+ * @param expr - The SetFlowVariables flow logic instance shape
351
+ * @returns Error message if validation fails, undefined if valid
352
+ *
353
+ * @example
354
+ * // Valid usage
355
+ * wfa.flowLogic.setFlowVariables(
356
+ * { $id: Now.ID['...'] },
357
+ * params.flowVariables, // ← Schema reference (2nd argument)
358
+ * { user: params.trigger.name, count: 42, active: true }
359
+ * )
360
+ */
361
+ function validateSetFlowVariables(expr: FlowLogicInstanceShape): string | undefined {
362
+ if (!isSetFlowVariablesShape(expr)) {
363
+ return undefined
364
+ }
365
+
366
+ // Validate argument count
367
+ const args = expr.getArguments()
368
+ if (args.length !== 3) {
369
+ return `SetFlowVariables requires exactly 3 arguments (config, schema, values), but received ${args.length}`
370
+ }
371
+
372
+ // Validate config argument
373
+ try {
374
+ expr.getSysId()
375
+ } catch (error) {
376
+ return 'SetFlowVariables: First argument (config) must be an object with valid $id property'
377
+ }
378
+
379
+ // Validate values argument (third argument)
380
+ const valuesArg = expr.getVariablesToSet()
381
+ if (!valuesArg || valuesArg.isUndefined()) {
382
+ return 'SetFlowVariables: Third argument (values) is required'
383
+ }
384
+
385
+ if (!valuesArg.isObject()) {
386
+ return 'SetFlowVariables: Third argument (values) must be an object'
387
+ }
388
+
389
+ // Validate that values object is not empty
390
+ const entries = Array.from(valuesArg.entries({ resolve: false }))
391
+ if (entries.length === 0) {
392
+ return 'SetFlowVariables: Values object cannot be empty - at least one variable must be set'
393
+ }
394
+
395
+ // Validate each value in the object
396
+ for (const [key, valueShape] of entries) {
397
+ if (!key || key.trim() === '') {
398
+ return 'SetFlowVariables: Variable names cannot be empty'
399
+ }
400
+
401
+ // Check if value is valid (string, datapill, template expression, or inline script)
402
+ if (valueShape.isUndefined()) {
403
+ return `SetFlowVariables: Variable '${key}' has undefined value`
404
+ }
405
+
406
+ // Values can be: strings, numbers, booleans, objects, arrays, datapills, template expressions, or inline scripts
407
+ const isDatapill = valueShape instanceof PropertyAccessShape || valueShape instanceof TemplateExpressionShape
408
+ const isInlineScript = valueShape instanceof FDInlineScriptCallShape
409
+ const isIdentifier = valueShape instanceof IdentifierShape
410
+ const isArrayOrObject = valueShape instanceof ArrayShape || valueShape instanceof ObjectShape
411
+ const isValidType =
412
+ valueShape.isString() ||
413
+ valueShape.isNumber() ||
414
+ valueShape.isBoolean() ||
415
+ isDatapill ||
416
+ isArrayOrObject ||
417
+ isInlineScript
418
+
419
+ if (!isValidType) {
420
+ // Provide specific error message for unsupported types
421
+ if (isIdentifier) {
422
+ return `SetFlowVariables: Variable '${key}' cannot use local variable references. Use direct values (literals) or datapills (e.g., params.someField) instead`
423
+ }
424
+ return `SetFlowVariables: Variable '${key}' has invalid value type. Expected string, number, boolean, object, array, or datapill expression`
425
+ }
426
+ }
427
+
428
+ return undefined
429
+ }
430
+
431
+ /**
432
+ * Validates AssignSubflowOutputs flow logic instance.
433
+ * Performs comprehensive validation of arguments, types, structure, and placement.
434
+ *
435
+ * **Validations performed:**
436
+ * 1. Placement: Must be within a Subflow or SubflowDefinition (not in regular Flow)
437
+ * 2. Argument count: Must have exactly 3 arguments
438
+ * 3. Config object: Must contain required $id property
439
+ * 4. Schema argument: Must be params.outputs (schema reference)
440
+ * 5. Values object: Must be non-empty
441
+ * 6. Output names: Cannot be empty or whitespace
442
+ * 7. Output values: Must be valid types (string, number, boolean, or datapill)
443
+ *
444
+ * **Valid value types:**
445
+ * - String literals: "success"
446
+ * - Numbers: 42, 3.14
447
+ * - Booleans: true, false
448
+ * - Objects: { a: "value", b: 42 } (ObjectShape - for FlowObject types)
449
+ * - Arrays: [1, 2, 3] (ArrayShape - for FlowArray types)
450
+ * - Datapills: params.action.result, params.complexObject (PropertyAccessShape)
451
+ * - Template expressions: `Result: ${params.action.result}` (TemplateExpressionShape)
452
+ *
453
+ * **Important:** AssignSubflowOutputs can ONLY be used within Subflow or SubflowDefinition.
454
+ * Using it in a regular Flow will result in a validation error.
455
+ *
456
+ * @param expr - The AssignSubflowOutputs flow logic instance shape
457
+ * @returns Error message if validation fails, undefined if valid
458
+ *
459
+ * @example
460
+ * // Valid usage (within Subflow)
461
+ * Subflow({
462
+ * outputs: { result: StringColumn(...) }
463
+ * }, (params) => {
464
+ * wfa.flowLogic.assignSubflowOutputs(
465
+ * { $id: Now.ID['...'] },
466
+ * params.outputs, // ← Schema reference (2nd argument)
467
+ * { result: params.action.data, status: "complete" }
468
+ * )
469
+ * })
470
+ */
471
+ function validateAssignSubflowOutputs(expr: FlowLogicInstanceShape): string | undefined {
472
+ if (!isAssignSubflowOutputsShape(expr)) {
473
+ return undefined
474
+ }
475
+
476
+ // Validate that this is called within a SubflowDefinition or Subflow
477
+ const node = expr.getOriginalNode()
478
+ const subflowAncestor =
479
+ findAncestorByCalleeName(node, 'SubflowDefinition') || findAncestorByCalleeName(node, 'Subflow')
480
+ if (!subflowAncestor) {
481
+ return 'AssignSubflowOutputs can only be used within a SubflowDefinition or Subflow'
482
+ }
483
+
484
+ // Validate argument count
485
+ const args = expr.getArguments()
486
+ if (args.length !== 3) {
487
+ return `AssignSubflowOutputs requires exactly 3 arguments (config, schema, values), but received ${args.length}`
488
+ }
489
+
490
+ // Validate config argument
491
+ try {
492
+ expr.getSysId()
493
+ } catch (error) {
494
+ return 'AssignSubflowOutputs: First argument (config) must be an object with valid $id property'
495
+ }
496
+
497
+ // Validate values argument (third argument)
498
+ const valuesArg = expr.getAssignedSubflowOutputs()
499
+ if (!valuesArg || valuesArg.isUndefined()) {
500
+ return 'AssignSubflowOutputs: Third argument (values) is required'
501
+ }
502
+
503
+ if (!valuesArg.isObject()) {
504
+ return 'AssignSubflowOutputs: Third argument (values) must be an object'
505
+ }
506
+
507
+ // Validate that values object is not empty
508
+ const entries = Array.from(valuesArg.entries({ resolve: false }))
509
+ if (entries.length === 0) {
510
+ return 'AssignSubflowOutputs: Values object cannot be empty - at least one output must be assigned'
511
+ }
512
+
513
+ // Validate each value in the object
514
+ for (const [key, valueShape] of entries) {
515
+ if (!key || key.trim() === '') {
516
+ return 'AssignSubflowOutputs: Output names cannot be empty'
517
+ }
518
+
519
+ // Check if value is valid (string, datapill, template expression, or inline script)
520
+ if (valueShape.isUndefined()) {
521
+ return `AssignSubflowOutputs: Output '${key}' has undefined value`
522
+ }
523
+
524
+ // Values can be: strings, numbers, booleans, objects, arrays, datapills, template expressions, or inline scripts
525
+ const isDatapill = valueShape instanceof PropertyAccessShape || valueShape instanceof TemplateExpressionShape
526
+ const isInlineScript = valueShape instanceof FDInlineScriptCallShape
527
+ const isIdentifier = valueShape instanceof IdentifierShape
528
+ const isArrayOrObject = valueShape instanceof ArrayShape || valueShape instanceof ObjectShape
529
+ const isValidType =
530
+ valueShape.isString() ||
531
+ valueShape.isNumber() ||
532
+ valueShape.isBoolean() ||
533
+ isDatapill ||
534
+ isArrayOrObject ||
535
+ isInlineScript
536
+
537
+ if (!isValidType) {
538
+ // Provide specific error message for unsupported types
539
+ if (isIdentifier) {
540
+ return `AssignSubflowOutputs: Output '${key}' cannot use local variable references. Use direct values (literals) or datapills (e.g., params.someField) instead`
541
+ }
542
+ return `AssignSubflowOutputs: Output '${key}' has invalid value type. Expected string, number, boolean, object, array, or datapill expression`
543
+ }
544
+ }
545
+
546
+ return undefined
547
+ }
548
+
549
+ /**
550
+ * Validates that a loop control flow logic (Exit Loop or Skip Iteration) is within a valid loop construct.
551
+ *
552
+ * @param expr - The flow logic instance shape to validate
553
+ * @param logicName - The name of the logic for error messages (e.g., 'Exit Loop', 'Skip Iteration')
554
+ * @returns Error message if placement is invalid, undefined if valid
555
+ */
556
+ function validateLoopPlacement(expr: FlowLogicInstanceShape, logicName: string): string | undefined {
557
+ const node = expr.getOriginalNode()
558
+
559
+ // Loop constructs that loop control flow logic can be used within
560
+ const LOOP_CONSTRUCTS = [
561
+ FLOW_LOGIC.FOR_EACH,
562
+ // TODO: Add FLOW_LOGIC.DO_UNTIL when implemented
563
+ ]
564
+
565
+ const parentLoop = findAncestorByCalleeName(node, ...LOOP_CONSTRUCTS)
566
+ if (!parentLoop) {
567
+ return `${logicName} must be used within a Do Until or For Each loop`
568
+ }
569
+
570
+ return undefined
571
+ }
572
+
573
+ function validateEndFlowPlacement(expr: FlowLogicInstanceShape): string | undefined {
574
+ const node = expr.getOriginalNode()
575
+
576
+ // Block constructs that End Flow can be used within
577
+ const END_FLOW_BLOCKS = [
578
+ FLOW_LOGIC.FOR_EACH,
579
+ FLOW_LOGIC.IF,
580
+ FLOW_LOGIC.ELSEIF,
581
+ FLOW_LOGIC.ELSE,
582
+ // TODO: Add FLOW_LOGIC.DO_UNTIL when implemented
583
+ ]
584
+
585
+ const parentBlock = findAncestorByCalleeName(node, ...END_FLOW_BLOCKS)
586
+ if (!parentBlock) {
587
+ return 'End Flow must be used within a Do Until, For Each, or If block'
588
+ }
589
+
590
+ return undefined
591
+ }