@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,875 @@
1
+ import {
2
+ type Record,
3
+ UndefinedShape,
4
+ type Diagnostics,
5
+ CallExpressionShape,
6
+ type Logger,
7
+ } from '@servicenow/sdk-build-core'
8
+ import { parseAttributesToObject } from './schema-to-flow-object'
9
+ import { STRING_API_NAME, STRING_FULL_UTF8_ATTRIBUTE_NAME, STRING_FULL_UTF8_DATA_TYPE_VALUE } from './flow-constants'
10
+
11
+ /**
12
+ * Utility module responsible for resolving complex-object and array inputs to the
13
+ * JSON payload expected by Flow Designer. Keeping the logic in a standalone
14
+ * file makes it unit-testable and keeps plugin code succinct.
15
+ */
16
+
17
+ /* -------------------------------------------------------------------------- */
18
+ /* Constants */
19
+ /* -------------------------------------------------------------------------- */
20
+
21
+ /** Prefix for Flow Designer complex object schema keys */
22
+ const FLOW_DESIGNER_PREFIX = 'FlowDesigner:'
23
+
24
+ /** Suffix for field facets in complex object schema */
25
+ const FIELD_FACETS_SUFFIX = '.$field_facets'
26
+
27
+ /** Key for SimpleMapFacet in field facets */
28
+ const SIMPLE_MAP_FACET_KEY = 'SimpleMapFacet'
29
+
30
+ /** Prefix for Java language types in complex objects */
31
+ const JAVA_LANG_PREFIX = 'java.lang.'
32
+
33
+ /** Field name for complex object name in JSON payload */
34
+ const COMPLEX_OBJECT_NAME_FIELD = 'name$'
35
+
36
+ /** Field name for complex object collection arrays in JSON payload */
37
+ const COMPLEX_OBJECT_COLLECTION_FIELD = '$COCollectionField'
38
+
39
+ /** UI type value for object type fields */
40
+ const UI_TYPE_OBJECT = 'object'
41
+
42
+ /** UI type prefix for array type fields */
43
+ const UI_TYPE_ARRAY_PREFIX = 'array'
44
+
45
+ /* -------------------------------------------------------------------------- */
46
+ /* Type Definitions */
47
+ /* -------------------------------------------------------------------------- */
48
+
49
+ /**
50
+ * Represents the complete complex object schema structure.
51
+ * The key is typically in the format "FlowDesigner:{typeName}".
52
+ * Extends Record for compatibility with existing code that uses unknown types.
53
+ */
54
+ interface ComplexObjectSchema extends globalThis.Record<string, unknown> {
55
+ [key: `FlowDesigner:${string}`]: ComplexObjectTemplate
56
+ }
57
+
58
+ /**
59
+ * Template defining the structure of a complex object with field definitions and metadata.
60
+ * Can contain field names mapped to types (string), nested objects, or field facets.
61
+ */
62
+ interface ComplexObjectTemplate extends globalThis.Record<string, unknown> {
63
+ [fieldName: string]: string | ComplexObjectTemplate | FieldFacets | unknown
64
+ }
65
+
66
+ /**
67
+ * Field facets containing metadata for a complex object field.
68
+ * The key is in the format "{fieldName}.$field_facets".
69
+ */
70
+ interface FieldFacets extends globalThis.Record<string, unknown> {
71
+ SimpleMapFacet?: string // JSON-stringified SimpleMapFacet object
72
+ [facetType: string]: string | unknown
73
+ }
74
+
75
+ /**
76
+ * Simple map facet containing field label, type, and mapped datapill values.
77
+ * This is typically stored as a JSON-stringified object in the schema.
78
+ */
79
+ interface SimpleMapFacet {
80
+ label?: string
81
+ uiType?: string
82
+ mapped?: string // JSON-stringified object mapping dotted paths to datapill values
83
+ [key: string]: unknown
84
+ }
85
+
86
+ /* -------------------------------------------------------------------------- */
87
+ /* Public API */
88
+ /* -------------------------------------------------------------------------- */
89
+
90
+ export function resolveComplexInput(
91
+ name: string,
92
+ value: unknown,
93
+ parentDef: Record,
94
+ inputTableName: string,
95
+ diagnostics?: Diagnostics,
96
+ logger?: Logger
97
+ ): { value: unknown; internalType: unknown; children?: unknown[] } {
98
+ const inputDef = parentDef
99
+ ?.flat()
100
+ .filter((obj) => obj.getTable() === inputTableName)
101
+ .find((obj) => obj.get('element').asString().getValue() === name)
102
+
103
+ if (!inputDef) {
104
+ return { value: value, internalType: undefined }
105
+ }
106
+
107
+ let internalType = inputDef?.get('internal_type').asString().getValue()
108
+
109
+ //Logic to check if the StringColumn has isFullUTF8 set to true and update internalType to String (Full UTF-8)
110
+ const inputDefSource = inputDef.getSource()
111
+ if (inputDefSource instanceof CallExpressionShape && inputDefSource.getCallee() === STRING_API_NAME) {
112
+ const isFullUTF8 = inputDefSource.getArgument?.(0)?.asObject()?.get(STRING_FULL_UTF8_ATTRIBUTE_NAME)
113
+ if (isFullUTF8?.ifBoolean()?.getValue() === true) {
114
+ internalType = STRING_FULL_UTF8_DATA_TYPE_VALUE
115
+ }
116
+ }
117
+
118
+ const attributesShape = inputDef.get('attributes')
119
+ const attributesStr =
120
+ attributesShape && !attributesShape.is(UndefinedShape) ? attributesShape.ifString()?.getValue() : undefined
121
+
122
+ // If attributes is not present then its a primitive input, return the value as is.
123
+ if (!attributesStr) {
124
+ return { value: value, internalType: internalType }
125
+ }
126
+
127
+ const { coType, uiType } = parseAttributes(attributesStr)
128
+ if (!coType || !uiType) {
129
+ return { value: value, internalType: internalType }
130
+ }
131
+
132
+ const complexSchema = getComplexObjectSchema(parentDef, coType, diagnostics)
133
+ if (!complexSchema) {
134
+ return { value: value, internalType: internalType }
135
+ }
136
+
137
+ if (uiType === UI_TYPE_OBJECT) {
138
+ const result = buildObjectPayloadWithChildren(value, complexSchema, coType)
139
+ return {
140
+ value: result.value,
141
+ internalType: internalType,
142
+ children: result.children,
143
+ }
144
+ }
145
+
146
+ const uiTypeRoot = uiType.split('.')[0]
147
+ if (uiTypeRoot === UI_TYPE_ARRAY_PREFIX) {
148
+ const result = buildArrayPayloadWithChildren(value, complexSchema, coType, logger)
149
+ return {
150
+ value: result.value,
151
+ internalType: internalType,
152
+ children: result.children,
153
+ }
154
+ }
155
+
156
+ // Fallback - unsupported uiType
157
+ return { value: value, internalType: internalType }
158
+ }
159
+
160
+ /* -------------------------------------------------------------------------- */
161
+ /* Implementation */
162
+ /* -------------------------------------------------------------------------- */
163
+
164
+ interface ParsedAttributes {
165
+ coType?: string
166
+ uiType?: string
167
+ }
168
+
169
+ function parseAttributes(attr: string): ParsedAttributes {
170
+ const attributes = parseAttributesToObject(attr)
171
+ const coType = attributes['co_type_name']
172
+ const uiType = attributes['uiType']
173
+ const result: ParsedAttributes = {}
174
+ if (coType !== undefined) {
175
+ result.coType = coType
176
+ }
177
+ if (uiType !== undefined) {
178
+ result.uiType = uiType
179
+ }
180
+ return result
181
+ }
182
+
183
+ function getComplexObjectSchema(
184
+ parent: Record,
185
+ coType: string,
186
+ diagnostics?: Diagnostics
187
+ ): ComplexObjectSchema | undefined {
188
+ // get complex object schema from parent record for the given coType
189
+ const complexObject = parent
190
+ ?.flat()
191
+ .find((obj) => obj.getTable() === 'sys_complex_object' && obj.get('name').asString().getValue() === coType)
192
+
193
+ if (!complexObject) {
194
+ diagnostics?.error(parent, `Complex object '${coType}' not found.`)
195
+ return undefined
196
+ }
197
+
198
+ const serialized = complexObject?.get('serialized_content')?.ifString()?.getValue()
199
+ if (!serialized) {
200
+ diagnostics?.error(complexObject ?? parent, `Serialized schema missing for complex object '${coType}'.`)
201
+ return undefined
202
+ }
203
+
204
+ return safeJsonParse(serialized, coType, complexObject, diagnostics)
205
+ }
206
+
207
+ function safeJsonParse(
208
+ text: string,
209
+ coType: string,
210
+ node: Record,
211
+ diagnostics?: Diagnostics
212
+ ): ComplexObjectSchema | undefined {
213
+ try {
214
+ return JSON.parse(text) as ComplexObjectSchema
215
+ } catch (e: unknown) {
216
+ const message = e instanceof Error ? e.message : String(e)
217
+ diagnostics?.error(node, `Invalid schema JSON for complex object '${coType}': ${message}`)
218
+ return undefined
219
+ }
220
+ }
221
+
222
+ /* ------------------------------ Object Types ------------------------------ */
223
+
224
+ /** Enriches schema with mapped datapill values for nested objects */
225
+ function addMappedFieldsToSchema(
226
+ schema: ComplexObjectSchema,
227
+ coType: string,
228
+ rawValue: globalThis.Record<string, unknown>
229
+ ): ComplexObjectSchema {
230
+ // Deep clone the schema to avoid mutating the original
231
+ const enrichedSchema = JSON.parse(JSON.stringify(schema)) as ComplexObjectSchema
232
+ const template = enrichedSchema[`${FLOW_DESIGNER_PREFIX}${coType}`]
233
+
234
+ if (!template) {
235
+ return enrichedSchema
236
+ }
237
+
238
+ // Recursively process all fields (including nested objects)
239
+ processFieldsForMappedValues(template as globalThis.Record<string, unknown>, rawValue, '')
240
+
241
+ return enrichedSchema
242
+ }
243
+
244
+ /**
245
+ * Processes a single field to add mapped datapill value to its facets.
246
+ * @param facets - The field facets object
247
+ * @param mappedKey - The dotted path key (e.g., 'name.firstName')
248
+ * @param dataPillValue - The datapill value to map
249
+ */
250
+ function addMappedValueToFacet(facets: FieldFacets, mappedKey: string, dataPillValue: string): void {
251
+ const simpleMapFacetStr = facets[SIMPLE_MAP_FACET_KEY]
252
+
253
+ if (typeof simpleMapFacetStr !== 'string') {
254
+ return
255
+ }
256
+
257
+ try {
258
+ const facetObj = JSON.parse(simpleMapFacetStr) as SimpleMapFacet
259
+ const strippedValue = stripDataPillType(dataPillValue)
260
+ facetObj['mapped'] = JSON.stringify({ [mappedKey]: strippedValue })
261
+ facets[SIMPLE_MAP_FACET_KEY] = JSON.stringify(facetObj)
262
+ } catch (e) {
263
+ // Skip fields without proper facet structure
264
+ }
265
+ }
266
+
267
+ /** Recursively processes fields to add mapped datapill values for nested objects */
268
+ function processFieldsForMappedValues(
269
+ template: globalThis.Record<string, unknown>,
270
+ rawValue: globalThis.Record<string, unknown>,
271
+ parentPath: string
272
+ ): void {
273
+ for (const key of Object.keys(rawValue)) {
274
+ const fieldValue = rawValue[key]
275
+ const fieldTemplate = template[key]
276
+
277
+ // Handle arrays (FlowArray with FlowObject elements)
278
+ if (Array.isArray(fieldValue) && Array.isArray(fieldTemplate)) {
279
+ processArrayForMappedValues(fieldTemplate, fieldValue, parentPath, key)
280
+ continue
281
+ }
282
+
283
+ // Handle nested objects recursively
284
+ if (isNestedObject(fieldValue) && isNestedObject(fieldTemplate)) {
285
+ const newPath = buildFieldPath(parentPath, key)
286
+ processFieldsForMappedValues(fieldTemplate, fieldValue, newPath)
287
+ continue
288
+ }
289
+
290
+ // Handle datapill fields - add mapped value to facets
291
+ if (!isDataPill(fieldValue)) {
292
+ continue
293
+ }
294
+
295
+ const facetKey = `${key}${FIELD_FACETS_SUFFIX}`
296
+ const facets = template[facetKey]
297
+
298
+ if (!isNestedObject(facets)) {
299
+ continue
300
+ }
301
+
302
+ const mappedKey = buildFieldPath(parentPath, key)
303
+ addMappedValueToFacet(facets as FieldFacets, mappedKey, fieldValue as string)
304
+ }
305
+ }
306
+
307
+ /** Processes array elements to add mapped datapill values for FlowArray fields */
308
+ function processArrayForMappedValues(
309
+ templateArray: unknown[],
310
+ rawArray: unknown[],
311
+ parentPath: string,
312
+ arrayKey: string
313
+ ): void {
314
+ // FlowArray schema is wrapped: [{"wrapperKey": {field1: "String", field2: "Integer"}}]
315
+ if (templateArray.length !== 1) {
316
+ return
317
+ }
318
+
319
+ const wrapperElement = templateArray[0]
320
+ if (!isNestedObject(wrapperElement)) {
321
+ return
322
+ }
323
+
324
+ const wrapperKeys = Object.keys(wrapperElement)
325
+ if (wrapperKeys.length !== 1 || !wrapperKeys[0]) {
326
+ return
327
+ }
328
+
329
+ const elementTemplate = wrapperElement[wrapperKeys[0]]
330
+ if (!isNestedObject(elementTemplate)) {
331
+ return
332
+ }
333
+
334
+ // Process each array element
335
+ rawArray.forEach((element, index) => {
336
+ if (!isNestedObject(element)) {
337
+ return
338
+ }
339
+
340
+ // Build path with array index: "tasks[0]"
341
+ const arrayPath = `${arrayKey}[${index}]`
342
+ const fullPath = buildFieldPath(parentPath, arrayPath)
343
+
344
+ // Process fields in this array element
345
+ processFieldsForMappedValues(elementTemplate, element, fullPath)
346
+ })
347
+ }
348
+
349
+ /** Builds complex object payload with children array for UI display */
350
+ function buildObjectPayloadWithChildren(
351
+ rawValue: unknown,
352
+ schema: ComplexObjectSchema,
353
+ coType: string
354
+ ): { value: string; children: unknown[] } {
355
+ if (typeof rawValue !== 'object' || rawValue === null) {
356
+ return { value: String(rawValue), children: [] }
357
+ }
358
+
359
+ const template = schema[`${FLOW_DESIGNER_PREFIX}${coType}`]
360
+ const picked = deepPick(template, rawValue)
361
+ const cvObject = buildCv(picked, rawValue)
362
+
363
+ const enrichedSchema = addMappedFieldsToSchema(schema, coType, rawValue as globalThis.Record<string, unknown>)
364
+ const value = stringifyPayload(enrichedSchema, cvObject as globalThis.Record<string, unknown>)
365
+
366
+ // Build children array recursively for nested objects
367
+ const children = buildChildrenArray(
368
+ rawValue as globalThis.Record<string, unknown>,
369
+ template as globalThis.Record<string, unknown>
370
+ )
371
+
372
+ return { value, children }
373
+ }
374
+
375
+ /* ------------------------------ Array Types ------------------------------- */
376
+
377
+ function buildArrayPayload(rawValue: unknown, schema: ComplexObjectSchema, coType: string): string {
378
+ const collectionValue =
379
+ Array.isArray(rawValue) && rawValue.length === 0
380
+ ? (createEmptyArrayPlaceholder(schema, coType) ?? rawValue)
381
+ : rawValue
382
+
383
+ return stringifyPayload(schema, {
384
+ [COMPLEX_OBJECT_NAME_FIELD]: coType,
385
+ [COMPLEX_OBJECT_COLLECTION_FIELD]: collectionValue,
386
+ })
387
+ }
388
+
389
+ /**
390
+ * Builds complex object array payload with children array for UI display.
391
+ * Extracts child_name from schema and uses it for array element names.
392
+ */
393
+ function buildArrayPayloadWithChildren(
394
+ rawValue: unknown,
395
+ schema: ComplexObjectSchema,
396
+ coType: string,
397
+ logger?: Logger
398
+ ): { value: string; children: unknown[] } {
399
+ // Build the payload value
400
+ const value = buildArrayPayload(rawValue, schema, coType)
401
+
402
+ // Extract child_name from schema
403
+ const childName = extractChildNameFromSchema(schema, coType, logger)
404
+
405
+ // Build children array with proper names
406
+ const children: unknown[] = []
407
+ if (Array.isArray(rawValue)) {
408
+ const template = schema[`${FLOW_DESIGNER_PREFIX}${coType}`]
409
+ const collectionField = template?.[COMPLEX_OBJECT_COLLECTION_FIELD]
410
+ const elementTemplate =
411
+ Array.isArray(collectionField) && collectionField.length > 0 ? collectionField[0] : undefined
412
+
413
+ for (const element of rawValue) {
414
+ if (typeof element === 'object' && element !== null && elementTemplate) {
415
+ // Unwrap childName layer if present
416
+ // The schema wraps FlowObject fields with childName: { "tag": { "value": "String", ... } }
417
+ // We need to extract the inner object: { "value": "String", ... }
418
+ let actualTemplate = elementTemplate as globalThis.Record<string, unknown>
419
+ if (childName && childName in actualTemplate) {
420
+ const innerTemplate = actualTemplate[childName]
421
+ if (typeof innerTemplate === 'object' && innerTemplate !== null && !Array.isArray(innerTemplate)) {
422
+ actualTemplate = innerTemplate as globalThis.Record<string, unknown>
423
+ }
424
+ }
425
+
426
+ // For complex elements (objects), recursively build children
427
+ const elementChildren = buildChildrenArray(
428
+ element as globalThis.Record<string, unknown>,
429
+ actualTemplate
430
+ )
431
+ children.push({
432
+ name: childName || '',
433
+ value: '',
434
+ displayValue: '',
435
+ children: elementChildren,
436
+ })
437
+ } else {
438
+ // For primitive elements
439
+ children.push({
440
+ name: childName || '',
441
+ value: String(element),
442
+ displayValue: String(element),
443
+ })
444
+ }
445
+ }
446
+ }
447
+
448
+ return { value, children }
449
+ }
450
+
451
+ /**
452
+ * Extracts child_name from a complex object schema.
453
+ * The child_name is stored in the $COCollectionField.$type_facets.SimpleMapFacet.
454
+ */
455
+ function extractChildNameFromSchema(schema: ComplexObjectSchema, coType: string, logger?: Logger): string | undefined {
456
+ try {
457
+ const template = schema[`${FLOW_DESIGNER_PREFIX}${coType}`]
458
+ const typeFacets = template?.['$COCollectionField.$type_facets']
459
+
460
+ if (typeFacets && typeof typeFacets === 'object' && 'SimpleMapFacet' in typeFacets) {
461
+ const simpleMapFacet = typeFacets.SimpleMapFacet
462
+ if (typeof simpleMapFacet === 'string') {
463
+ const facetData = JSON.parse(simpleMapFacet)
464
+ return facetData.child_name
465
+ }
466
+ }
467
+ } catch (error) {
468
+ logger?.warn(
469
+ 'Failed to extract child_name from schema:',
470
+ error instanceof Error ? error.message : String(error)
471
+ )
472
+ }
473
+ return undefined
474
+ }
475
+
476
+ /**
477
+ * Creates a placeholder element for empty FlowArrays with FlowObject elements.
478
+ * ServiceNow expects a single placeholder with empty $cv values for each field.
479
+ *
480
+ * @param schema - The complex object schema containing array structure
481
+ * @param coType - The complex object type name
482
+ * @returns Array with single placeholder element, or undefined if schema is invalid
483
+ */
484
+ function createEmptyArrayPlaceholder(schema: ComplexObjectSchema, coType: string): unknown[] | undefined {
485
+ const template = schema[`${FLOW_DESIGNER_PREFIX}${coType}`]
486
+ const collectionField = template?.[COMPLEX_OBJECT_COLLECTION_FIELD]
487
+
488
+ if (!Array.isArray(collectionField) || collectionField.length === 0) {
489
+ return undefined
490
+ }
491
+
492
+ const elementTemplate = collectionField[0]
493
+ if (!isNestedObject(elementTemplate)) {
494
+ return undefined
495
+ }
496
+
497
+ const childSchemaKey = Object.keys(elementTemplate)[0]
498
+ if (!childSchemaKey) {
499
+ return undefined
500
+ }
501
+
502
+ const childSchema = elementTemplate[childSchemaKey]
503
+ if (!isNestedObject(childSchema)) {
504
+ return undefined
505
+ }
506
+
507
+ const placeholder = buildPlaceholderFromSchema(childSchema)
508
+ return [placeholder]
509
+ }
510
+
511
+ /**
512
+ * Builds a placeholder object with empty $cv wrappers for each non-metadata field.
513
+ *
514
+ * @param schema - Schema object mapping field names to types
515
+ * @returns Placeholder object with $cv wrappers
516
+ */
517
+ function buildPlaceholderFromSchema(schema: globalThis.Record<string, unknown>): globalThis.Record<string, unknown> {
518
+ const placeholder: globalThis.Record<string, unknown> = {}
519
+
520
+ for (const [fieldKey, fieldType] of Object.entries(schema)) {
521
+ if (isMetadataField(fieldKey) || typeof fieldType !== 'string') {
522
+ continue
523
+ }
524
+
525
+ placeholder[fieldKey] = {
526
+ $cv: {
527
+ $c: toJavaType(fieldType),
528
+ $v: '',
529
+ },
530
+ }
531
+ }
532
+
533
+ return placeholder
534
+ }
535
+
536
+ /* ------------------------------ Formatting -------------------------------- */
537
+
538
+ function stringifyPayload(schema: ComplexObjectSchema, complexObject: globalThis.Record<string, unknown>): string {
539
+ return JSON.stringify({
540
+ version: '1.0',
541
+ complexObjectSchema: schema,
542
+ complexObject,
543
+ serializationFormat: 'JSON',
544
+ })
545
+ }
546
+
547
+ /* ------------------------------ Helpers ----------------------------------- */
548
+
549
+ function deepPick(template: unknown, source: unknown): unknown {
550
+ if (typeof template !== 'object' || template === null) {
551
+ return template
552
+ }
553
+
554
+ // Handle FlowArray with FlowObject elements (wrapped schema format)
555
+ const unwrappedArray = tryUnwrapFlowArraySchema(template, source)
556
+ if (unwrappedArray !== null) {
557
+ return unwrappedArray
558
+ }
559
+
560
+ return pickMatchingFields(template, source)
561
+ }
562
+
563
+ /**
564
+ * Attempts to unwrap FlowArray schema and map source elements.
565
+ *
566
+ * FlowArray with FlowObject elements uses wrapped schema format:
567
+ * - Template: [{"fieldName": {field1: "String", field2: "Integer"}}]
568
+ * - Source: [{field1: "value1", field2: 123}, {field1: "value2", field2: 456}]
569
+ *
570
+ * @param template - The schema template (potentially wrapped array)
571
+ * @param source - The source data (array of actual objects)
572
+ * @returns Mapped array if successful, null if not a wrapped array schema
573
+ */
574
+ function tryUnwrapFlowArraySchema(template: unknown, source: unknown): unknown[] | null {
575
+ if (!Array.isArray(template) || !Array.isArray(source) || template.length !== 1) {
576
+ return null
577
+ }
578
+
579
+ const wrapperElement = template[0]
580
+ if (!isNestedObject(wrapperElement)) {
581
+ return null
582
+ }
583
+
584
+ const wrapperKeys = Object.keys(wrapperElement)
585
+ if (wrapperKeys.length !== 1 || !wrapperKeys[0]) {
586
+ return null
587
+ }
588
+
589
+ const unwrappedSchema = wrapperElement[wrapperKeys[0]]
590
+ if (!isNestedObject(unwrappedSchema)) {
591
+ return null
592
+ }
593
+
594
+ // Successfully unwrapped - map each source element through the schema
595
+ return source.map((sourceElement) => deepPick(unwrappedSchema, sourceElement))
596
+ }
597
+
598
+ /**
599
+ * Picks fields from source that exist in template, recursively.
600
+ *
601
+ * @param template - The schema template defining which fields to pick
602
+ * @param source - The source data to pick from
603
+ * @returns Object/array with only the fields that exist in both template and source
604
+ */
605
+ function pickMatchingFields(template: unknown, source: unknown): unknown {
606
+ const tmpl = template as globalThis.Record<string, unknown>
607
+ const src = source as globalThis.Record<string, unknown>
608
+ const result = (Array.isArray(template) ? [] : {}) as globalThis.Record<string, unknown>
609
+
610
+ for (const key of Object.keys(tmpl)) {
611
+ if (src && key in src) {
612
+ result[key] = deepPick(tmpl[key], src[key])
613
+ }
614
+ }
615
+
616
+ return result
617
+ }
618
+
619
+ function toJavaType(t: string): string {
620
+ // Date/DateTime fields should serialize as java.lang.String, not java.lang.Date
621
+ // ServiceNow Flow Designer UI expects date values to be strings in complexObject
622
+ // This matches the behavior when creating FlowObjects with Date fields through the UI
623
+ if (t === 'Date') {
624
+ return `${JAVA_LANG_PREFIX}String`
625
+ }
626
+ return `${JAVA_LANG_PREFIX}${t}`
627
+ }
628
+
629
+ /** Detects if value is a datapill ({{path}} or {{path|type}}) */
630
+ export function isDataPill(value: unknown): boolean {
631
+ if (typeof value !== 'string') {
632
+ return false
633
+ }
634
+ return value.startsWith('{{') && value.endsWith('}}')
635
+ }
636
+
637
+ /** Strips type annotation from datapill ({{path|type}} -> {{path}}) */
638
+ function stripDataPillType(value: unknown): string {
639
+ if (typeof value !== 'string' || !isDataPill(value)) {
640
+ return String(value)
641
+ }
642
+
643
+ const pipeIndex = value.lastIndexOf('|')
644
+ if (pipeIndex > 0 && value.endsWith('}}')) {
645
+ return value.substring(0, pipeIndex) + '}}'
646
+ }
647
+
648
+ return value
649
+ }
650
+
651
+ /** Checks if value is a nested object (not null or array) */
652
+ function isNestedObject(value: unknown): value is globalThis.Record<string, unknown> {
653
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
654
+ }
655
+
656
+ /** Builds dotted path for nested fields (e.g., 'name.firstName') */
657
+ function buildFieldPath(parentPath: string, key: string): string {
658
+ return parentPath ? `${parentPath}.${key}` : key
659
+ }
660
+
661
+ /** Checks if field key is metadata (contains $ or .) */
662
+ function isMetadataField(key: string): boolean {
663
+ return key.includes('$') || key.includes('.')
664
+ }
665
+
666
+ /** Checks if field value should be included in children array */
667
+ function shouldIncludeField(fieldValue: unknown): boolean {
668
+ return fieldValue !== undefined && fieldValue !== null && fieldValue !== ''
669
+ }
670
+
671
+ /** Child parameter metadata */
672
+ interface ChildParameter {
673
+ children: unknown[]
674
+ uiDisplayType: string
675
+ type_label: string
676
+ id: string
677
+ label: string
678
+ name: string
679
+ type: string
680
+ order: number
681
+ extended: boolean
682
+ mandatory: boolean
683
+ readOnly: boolean
684
+ hint: string
685
+ maxsize: number
686
+ reference: string
687
+ reference_display: string
688
+ choiceOption: string
689
+ table: string
690
+ columnName: string
691
+ defaultValue: string
692
+ defaultDisplayValue: string
693
+ use_dependent: boolean
694
+ fShowReferenceFinder: boolean
695
+ local: boolean
696
+ attributes: globalThis.Record<string, unknown>
697
+ ref_qual: string
698
+ dependent_on: string
699
+ }
700
+
701
+ /** Child element in children array */
702
+ interface ChildElement {
703
+ id: string
704
+ name: string
705
+ value: string
706
+ displayValue: string
707
+ children: unknown[]
708
+ parameter: ChildParameter
709
+ scriptActive: boolean
710
+ script: globalThis.Record<string, unknown>
711
+ }
712
+
713
+ /** Creates parameter object with default values */
714
+ function createChildParameter(key: string, type: string, uiDisplayType: string, typeLabel: string): ChildParameter {
715
+ return {
716
+ children: [],
717
+ uiDisplayType,
718
+ type_label: typeLabel,
719
+ id: '',
720
+ label: key,
721
+ name: key,
722
+ type,
723
+ order: 0,
724
+ extended: false,
725
+ mandatory: false,
726
+ readOnly: false,
727
+ hint: '',
728
+ maxsize: 0,
729
+ reference: '',
730
+ reference_display: '',
731
+ choiceOption: '',
732
+ table: '',
733
+ columnName: '',
734
+ defaultValue: '',
735
+ defaultDisplayValue: '',
736
+ use_dependent: false,
737
+ fShowReferenceFinder: false,
738
+ local: false,
739
+ attributes: {},
740
+ ref_qual: '',
741
+ dependent_on: '',
742
+ }
743
+ }
744
+
745
+ /** Creates child element */
746
+ function createChildElement(key: string, value: string, children: unknown[], parameter: ChildParameter): ChildElement {
747
+ return {
748
+ id: '',
749
+ name: key,
750
+ value,
751
+ displayValue: '',
752
+ children,
753
+ parameter,
754
+ scriptActive: false,
755
+ script: {},
756
+ }
757
+ }
758
+
759
+ /** Maps Java type to UI display type */
760
+ function getUiDisplayType(javaType: string): string {
761
+ switch (javaType) {
762
+ case 'String':
763
+ return 'string'
764
+ case 'Integer':
765
+ return 'integer'
766
+ case 'Boolean':
767
+ return 'boolean'
768
+ case 'Decimal':
769
+ return 'decimal'
770
+ case 'Number':
771
+ return 'decimal' // Number maps to decimal in UI
772
+ case 'Date':
773
+ return 'glide_date_time'
774
+ case 'Choice':
775
+ return 'choice'
776
+ default:
777
+ return 'string'
778
+ }
779
+ }
780
+
781
+ /** Maps Java type to type label */
782
+ function getTypeLabel(javaType: string): string {
783
+ switch (javaType) {
784
+ case 'String':
785
+ return 'String'
786
+ case 'Integer':
787
+ return 'Integer'
788
+ case 'Boolean':
789
+ return 'True/False'
790
+ case 'Decimal':
791
+ return 'Decimal'
792
+ case 'Number':
793
+ return 'Number'
794
+ case 'Date':
795
+ return 'Date/Time'
796
+ case 'Choice':
797
+ return 'Choice'
798
+ default:
799
+ return 'String'
800
+ }
801
+ }
802
+
803
+ /** Recursively builds children array for nested objects */
804
+ function buildChildrenArray(
805
+ rawValue: globalThis.Record<string, unknown>,
806
+ template: globalThis.Record<string, unknown>
807
+ ): unknown[] {
808
+ const children: unknown[] = []
809
+
810
+ Object.keys(template).forEach((key) => {
811
+ if (isMetadataField(key)) {
812
+ return
813
+ }
814
+
815
+ const fieldValue = rawValue[key]
816
+ const fieldType = template[key]
817
+
818
+ if (isNestedObject(fieldType)) {
819
+ // Nested object: recurse
820
+ const nestedChildren = isNestedObject(fieldValue) ? buildChildrenArray(fieldValue, fieldType) : []
821
+
822
+ const parameter = createChildParameter(key, 'object', 'object', 'Object')
823
+ children.push(createChildElement(key, '', nestedChildren, parameter))
824
+ } else if (typeof fieldType === 'string') {
825
+ // Primitive field with value
826
+ if (shouldIncludeField(fieldValue)) {
827
+ const value = isDataPill(fieldValue) ? stripDataPillType(fieldValue) : ''
828
+ const parameter = createChildParameter(
829
+ key,
830
+ fieldType.toLowerCase(),
831
+ getUiDisplayType(fieldType),
832
+ getTypeLabel(fieldType)
833
+ )
834
+ children.push(createChildElement(key, value, [], parameter))
835
+ }
836
+ }
837
+ })
838
+
839
+ return children
840
+ }
841
+
842
+ function buildCv(typeNode: unknown, valueNode: unknown): unknown {
843
+ if (typeof typeNode === 'object' && typeNode !== null) {
844
+ const typedNode = typeNode as globalThis.Record<string, unknown>
845
+ const valuedNode = valueNode as globalThis.Record<string, unknown> | undefined
846
+
847
+ // Special handling for primitive arrays (schema: ["Any"], value: ["item1", "item2", ...])
848
+ if (Array.isArray(typeNode) && Array.isArray(valueNode)) {
849
+ if (typeNode.length === 1 && typeNode[0] === 'Any') {
850
+ // Primitive array: return plain string values without $cv wrapping
851
+ return valueNode.map((v) => String(v))
852
+ }
853
+ }
854
+
855
+ const obj = (Array.isArray(typeNode) ? [] : {}) as globalThis.Record<string, unknown>
856
+ Object.keys(typedNode).forEach((k) => {
857
+ obj[k] = buildCv(typedNode[k], valuedNode ? valuedNode[k] : undefined)
858
+ })
859
+ return obj
860
+ }
861
+
862
+ if (typeof typeNode === 'string') {
863
+ // Set $v to empty for datapills; Flow Designer handles the pill notation
864
+ const cvValue = isDataPill(valueNode) ? '' : (valueNode ?? '')
865
+
866
+ return {
867
+ $cv: {
868
+ $c: toJavaType(typeNode),
869
+ $v: cvValue,
870
+ },
871
+ }
872
+ }
873
+
874
+ return {}
875
+ }