@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
@@ -163,13 +163,12 @@ async function generateRouteAttributeRecords(
163
163
  attrType: string,
164
164
  attrMap: Map<string, Record>,
165
165
  factory: Factory,
166
- diagnostics: Diagnostics,
167
- callExpression: CallExpressionShape
166
+ diagnostics: Diagnostics
168
167
  ): Promise<Record[]> {
169
168
  const records: Record[] = []
170
169
  for (const attr of attributes) {
171
170
  const attrRecord = await factory.createRecord({
172
- source: callExpression,
171
+ source: attr,
173
172
  table: `sys_ws_${attrType}`,
174
173
  explicitId: attr.asObject().get('$id'),
175
174
  properties: attr.asObject().transform(({ $ }) => ({
@@ -179,17 +178,19 @@ async function generateRouteAttributeRecords(
179
178
  example_value: $.from('exampleValue').def(''),
180
179
  web_service_definition: $.val(restDef.getId()),
181
180
  })),
181
+ installCategory: restDef.getInstallCategory(),
182
182
  })
183
183
 
184
184
  checkForDuplicateRecords(attrMap, attrRecord, attr.asObject(), diagnostics)
185
185
 
186
186
  const attributeMappingRecord = await factory.createRecord({
187
- source: callExpression,
187
+ source: attr,
188
188
  table: `sys_ws_${attrType}_map`,
189
189
  properties: attr.asObject().transform(({ $ }) => ({
190
190
  web_service_operation: $.val(routeDef.getId()),
191
191
  [`web_service_${attrType}`]: $.val(attrRecord.getId()),
192
192
  })),
193
+ installCategory: restDef.getInstallCategory(),
193
194
  })
194
195
 
195
196
  records.push(attrRecord.with(attributeMappingRecord))
@@ -293,8 +294,7 @@ async function generateRouteAndRouteAttrRecords(
293
294
  'header',
294
295
  headersMap,
295
296
  factory,
296
- diagnostics,
297
- callExpression
297
+ diagnostics
298
298
  )
299
299
 
300
300
  const routeParameters = route.get('parameters')?.ifArray()?.getElements() ?? []
@@ -309,8 +309,7 @@ async function generateRouteAndRouteAttrRecords(
309
309
  'query_parameter',
310
310
  parametersMap,
311
311
  factory,
312
- diagnostics,
313
- callExpression
312
+ diagnostics
314
313
  )
315
314
 
316
315
  routeRecords.push(routeRecord.with(...headerRecords, ...parameterRecords))
@@ -319,11 +318,11 @@ async function generateRouteAndRouteAttrRecords(
319
318
  return routeRecords
320
319
  }
321
320
 
322
- function validateAttributesAndAssociations(
321
+ function findOrphanedAttributes(
323
322
  attributes: Record[],
324
323
  attributeRouteAssociations: Record[],
325
324
  attributeType: string
326
- ) {
325
+ ): Record[] {
327
326
  const attributeIdToRecordMap = new Map<string, Record>()
328
327
  attributes.forEach((attribute) => {
329
328
  attributeIdToRecordMap.set(attribute.getId().getValue(), attribute)
@@ -337,20 +336,21 @@ function validateAttributesAndAssociations(
337
336
  })
338
337
  )
339
338
 
340
- const orphanedAttributes = Array.from(attributeIds).filter((id) => !referencedAttributeIds.has(id))
341
- if (orphanedAttributes.length > 0) {
342
- const orphanedAttributeNames = orphanedAttributes
343
- .map((id) => {
344
- const attribute = attributeIdToRecordMap.get(id)
345
- return attribute?.get('name')?.getValue() || id
346
- })
347
- .join(', ')
339
+ const orphanedAttributeIds = Array.from(attributeIds).filter((id) => !referencedAttributeIds.has(id))
340
+ return orphanedAttributeIds
341
+ .map((id) => attributeIdToRecordMap.get(id))
342
+ .filter((record): record is Record => record !== undefined)
343
+ }
348
344
 
349
- throw new Error(
350
- `Found ${orphanedAttributes.length} attribute record(s) without route associations: ${orphanedAttributeNames}. ` +
351
- `Either associate these attributes with routes or delete them.`
352
- )
353
- }
345
+ function validateAttributesAndAssociations(
346
+ attributes: Record[],
347
+ attributeRouteAssociations: Record[],
348
+ attributeType: string
349
+ ) {
350
+ const attributeIdToRecordMap = new Map<string, Record>()
351
+ attributes.forEach((attribute) => {
352
+ attributeIdToRecordMap.set(attribute.getId().getValue(), attribute)
353
+ })
354
354
 
355
355
  const invalidAttributeAssociations = attributeRouteAssociations.filter((association) => {
356
356
  const attr = association.get(`web_service_${attributeType}`)
@@ -467,9 +467,7 @@ export const RestApiPlugin = Plugin.create({
467
467
  * Case 1: No m2m records exists for a header or parameter record. Can happen in following scenarios:
468
468
  * - User has created a header or parameter record but these records are not associated with any routes on instance.
469
469
  * - User has removed all the m2m associations on instance but not the actual header or parameter record.
470
- * Solution: Throw error guiding user to do one of the following:
471
- * - Associate the header or parameter record with a route
472
- * - Delete the header or parameter record
470
+ * Solution: Return orphaned attributes as unhandled records for partial success
473
471
  *
474
472
  * Case 2: Deleting a header record on instance wouldn't delete the m2m records which map those headers to a route.
475
473
  * Solution: Throw error and request the user to cleanup the m2m records on instance.
@@ -477,6 +475,10 @@ export const RestApiPlugin = Plugin.create({
477
475
  validateAttributesAndAssociations(headers, headerRouteAssociations, 'header')
478
476
  validateAttributesAndAssociations(parameters, paramRouteAssociations, 'query_parameter')
479
477
 
478
+ const orphanedHeaders = findOrphanedAttributes(headers, headerRouteAssociations, 'header')
479
+ const orphanedParameters = findOrphanedAttributes(parameters, paramRouteAssociations, 'query_parameter')
480
+ const unhandledRecords = [...orphanedHeaders, ...orphanedParameters]
481
+
480
482
  const routesWithScript = await Promise.all(
481
483
  routes.map(async (r) => {
482
484
  const script = await NowIncludeShape.fromRecord(r, r.get('operation_script'), transform)
@@ -519,32 +521,42 @@ export const RestApiPlugin = Plugin.create({
519
521
  })
520
522
  )
521
523
 
524
+ const shape = new CallExpressionShape({
525
+ source: record,
526
+ callee: 'RestApi',
527
+ args: [
528
+ record
529
+ .transform(({ $ }) => ({
530
+ $id: $.val(NowIdShape.from(record)),
531
+ name: $,
532
+ active: $.toBoolean().def(true),
533
+ consumes: $.def(DEFAULT_MEDIA_TYPE),
534
+ produces: $.def(DEFAULT_MEDIA_TYPE),
535
+ enforceAcl: $.from('enforce_acl')
536
+ .map((v) => splitAcls(v))
537
+ .def([DEFAULT_REST_ENFORCED_ACL]),
538
+ serviceId: $.from('service_id'),
539
+ shortDescription: $.from('short_description').def(''),
540
+ policy: $.from('sys_policy').def(''),
541
+ docLink: $.from('doc_link').def(''),
542
+ routes: $.val(routesWithScript).def([]),
543
+ versions: $.val(versionsTransform(versions)).def([]),
544
+ }))
545
+ .withAliasedKeys(restDefAliases),
546
+ ],
547
+ })
548
+
549
+ if (unhandledRecords.length > 0) {
550
+ return {
551
+ success: 'partial',
552
+ value: shape,
553
+ unhandledRecords,
554
+ }
555
+ }
556
+
522
557
  return {
523
558
  success: true,
524
- value: new CallExpressionShape({
525
- source: record,
526
- callee: 'RestApi',
527
- args: [
528
- record
529
- .transform(({ $ }) => ({
530
- $id: $.val(NowIdShape.from(record)),
531
- name: $,
532
- active: $.toBoolean().def(true),
533
- consumes: $.def(DEFAULT_MEDIA_TYPE),
534
- produces: $.def(DEFAULT_MEDIA_TYPE),
535
- enforceAcl: $.from('enforce_acl')
536
- .map((v) => splitAcls(v))
537
- .def([DEFAULT_REST_ENFORCED_ACL]),
538
- serviceId: $.from('service_id'),
539
- shortDescription: $.from('short_description').def(''),
540
- policy: $.from('sys_policy').def(''),
541
- docLink: $.from('doc_link').def(''),
542
- routes: $.val(routesWithScript).def([]),
543
- versions: $.val(versionsTransform(versions)).def([]),
544
- }))
545
- .withAliasedKeys(restDefAliases),
546
- ],
547
- }),
559
+ value: shape,
548
560
  }
549
561
  },
550
562
  },
@@ -13,13 +13,12 @@ import {
13
13
  type Package,
14
14
  type Record,
15
15
  } from '@servicenow/sdk-build-core'
16
- import { NowConfig, path as pathModule, ts, type FileSystem } from '@servicenow/sdk-build-core'
16
+ import { NowConfig, path as pathModule, ts, type FileSystem, type Logger } from '@servicenow/sdk-build-core'
17
17
  import { RepackService } from '../repack'
18
18
  import { SBOMBuilder } from './sbom-builder'
19
19
  import isEqual from 'lodash/isEqual'
20
20
  import { INVALID_XML_CHARACTERS, applyPathMappings } from '../utils'
21
21
  import zip from 'lodash/zip'
22
- import type { DependencyNode } from '@servicenow/sdk-repack'
23
22
 
24
23
  const GLUE_CODE_PREFIX = '// @fluent-module'
25
24
  const GLUE_CODE_META_REGEX = new RegExp(`^${GLUE_CODE_PREFIX} (.*);(true|false);(.*)`) // name;isDefault;path
@@ -32,7 +31,34 @@ const GLUE_CODE_WARNING = `
32
31
  // SDK from regenerating it. However, you will then be responsible for the
33
32
  // management of this code in your Fluent file.`
34
33
 
35
- const NODE_MODULES = 'node_modules'
34
+ export const NODE_MODULES = 'node_modules'
35
+
36
+ /**
37
+ * Check if a module matches any trusted module patterns.
38
+ * Supports exact matches ('lodash', '@servicenow/sdk') and org wildcards ('@servicenow/*').
39
+ * Invalid patterns (like '*' or 'lodash-*-utils') are ignored.
40
+ */
41
+ function isModuleTrusted(moduleName: string, trustedModules: string[], logger: Logger): boolean {
42
+ if (trustedModules.length === 0) {
43
+ return false
44
+ }
45
+
46
+ return trustedModules.some((pattern) => {
47
+ // @org/* pattern
48
+ if (pattern.startsWith('@') && pattern.endsWith('/*')) {
49
+ return moduleName.startsWith(pattern.slice(0, -1))
50
+ }
51
+
52
+ // Exact match (no wildcards allowed)
53
+ if (!pattern.includes('*')) {
54
+ return moduleName === pattern
55
+ }
56
+
57
+ // Invalid pattern, ignore
58
+ logger.warn(`Invalid trusted module pattern used in fluent config: ${pattern}`)
59
+ return false
60
+ })
61
+ }
36
62
 
37
63
  type GlueCodeMeta = {
38
64
  name: string
@@ -223,41 +249,7 @@ function isValidRequireCall(callExpression: ts.CallExpression, requirePath: ts.S
223
249
  return isRequire && !isRelativePath
224
250
  }
225
251
 
226
- function buildParentPathMap(dependencyNodes: DependencyNode[]): { [key: string]: string[] } {
227
- const importerMap: { [key: string]: string[] } = {}
228
- for (const node of dependencyNodes) {
229
- let parent = node.parentPackage
230
-
231
- while (parent) {
232
- const importerMapKey = `${node.pkgName}@${node.updatedManifest.version}`
233
- if (!importerMap[importerMapKey]) {
234
- importerMap[importerMapKey] = []
235
- }
236
- if (parent.pkgName) {
237
- importerMap[importerMapKey].push(parent.pkgName)
238
- }
239
-
240
- const newParent = dependencyNodes.find((potentialParent) => {
241
- if (!parent || !parent.pkgName) {
242
- return false
243
- }
244
- if (potentialParent.updatedManifest.dependencies[parent!.pkgName]) {
245
- return potentialParent
246
- }
247
- return false
248
- })
249
- parent = newParent
250
- ? {
251
- pkgName: newParent.updatedManifest.name,
252
- version: newParent.updatedManifest.version,
253
- }
254
- : undefined
255
- }
256
- }
257
- return importerMap
258
- }
259
-
260
- class ModuleDependencyShape extends Shape {
252
+ export class ModuleDependencyShape extends Shape {
261
253
  private readonly moduleName: string
262
254
 
263
255
  constructor({
@@ -278,9 +270,12 @@ class ModuleDependencyShape extends Shape {
278
270
 
279
271
  // TODO: Need to have some invalidation mechanism. Maybe the plugin framework can provide plugins with a managed cache to use for stuff like this?
280
272
  let DEPENDENCY_CACHE: globalThis.Record<string, Result<ModuleDependencyShape>> = {}
273
+ // Track external module record IDs for SBOM generation (not persisted to XML)
274
+ let EXTERNAL_MODULE_IDS: Set<string> = new Set()
281
275
  // Expose cache clearing for tests
282
276
  export function clearDependencyCache() {
283
277
  DEPENDENCY_CACHE = {}
278
+ EXTERNAL_MODULE_IDS = new Set()
284
279
  }
285
280
 
286
281
  function parseModuleDependency(
@@ -321,7 +316,11 @@ function parseModuleDependency(
321
316
 
322
317
  function generateSBOMContent(context: RecordContext) {
323
318
  const { database } = context
324
- const moduleRecords = database.query('sys_module', { external_source: true })
319
+ // Query sys_module records that are tracked as external
320
+ const moduleRecords = database.query('sys_module').filter((mod) => {
321
+ const recordId = mod.getId().getValue()
322
+ return EXTERNAL_MODULE_IDS.has(recordId)
323
+ })
325
324
  const sbomBuilder = new SBOMBuilder()
326
325
  for (const mod of moduleRecords) {
327
326
  const modulePath = mod.get('path').asString().getValue()
@@ -335,34 +334,16 @@ function generateSBOMContent(context: RecordContext) {
335
334
 
336
335
  function getModuleDependencyPath(
337
336
  config: NowConfig,
338
- module: { name: string; file: string; version: string; packageJson: Package; importerPath?: string[] }
337
+ module: { name: string; file: string; version: string; packageJson: Package; modulePath?: string }
339
338
  ) {
340
- const { name, file, packageJson, importerPath, version } = module
339
+ const { name, file, packageJson, modulePath, version } = module
341
340
 
342
341
  if (NowConfig.legacyPackageResolution(config)) {
343
342
  return NowConfig.moduleResolutionPath(config, packageJson, true, name, version, file)
344
343
  }
345
344
 
346
- if (config.hoistDependencies) {
347
- return NowConfig.moduleResolutionPath(config, packageJson, true, NODE_MODULES, name, file)
348
- }
349
-
350
- if (importerPath && importerPath.length > 0) {
351
- const pathSegments = [...importerPath].reverse()
352
- const pathSegmentsWithNodeModules: string[] = []
353
- pathSegments.forEach((segment) => {
354
- pathSegmentsWithNodeModules.push(NODE_MODULES)
355
- pathSegmentsWithNodeModules.push(segment)
356
- })
357
- return NowConfig.moduleResolutionPath(
358
- config,
359
- packageJson,
360
- true,
361
- ...pathSegmentsWithNodeModules,
362
- NODE_MODULES,
363
- name,
364
- file
365
- )
345
+ if (modulePath) {
346
+ return NowConfig.moduleResolutionPath(config, packageJson, true, modulePath, file)
366
347
  }
367
348
 
368
349
  return NowConfig.moduleResolutionPath(config, packageJson, true, NODE_MODULES, name, file)
@@ -477,7 +458,8 @@ export const ServerModulePlugin = Plugin.create({
477
458
  shape: ModuleDependencyShape,
478
459
  fileTypes: ['module'],
479
460
  // TODO: When managed cache is provided to plugins, cache dependencies that were already handled to avoid reprocessing
480
- async toRecord(shape, { packageJson, diagnostics, fs, logger, project, factory, config }) {
461
+ async toRecord(shape, context) {
462
+ const { packageJson, diagnostics, fs, logger, project, factory, config } = context
481
463
  if (config.type === 'configuration') {
482
464
  throw new Error(`Modules cannot be used in a configuration project`)
483
465
  }
@@ -491,27 +473,30 @@ export const ServerModulePlugin = Plugin.create({
491
473
  return { success: false }
492
474
  }
493
475
 
476
+ const isTrusted = isModuleTrusted(parentName, config.trustedModules, logger)
494
477
  const id = `${parentName}@${version}`
495
478
  const repack = await RepackService.create(logger, fs, project.getRootDir())
496
479
  const dependencyNodes = await repack.execute({
497
480
  id,
498
481
  entry: entry ? [entry] : ['.'],
482
+ legacyPackageResolution: NowConfig.legacyPackageResolution(config),
499
483
  })
500
484
  if (!dependencyNodes) {
501
485
  throw new Error(`Failed to build dependency ${id}`)
502
486
  }
503
487
 
504
- let importerMap: { [key: string]: string[] } = {}
505
- if (!config.hoistDependencies) {
506
- importerMap = buildParentPathMap(dependencyNodes)
507
- }
508
-
509
488
  const modules: { id: string; path: string; content: string }[] = []
510
489
  const { Lint } = await import('../repack/lint/index.js')
511
490
  for (const node of dependencyNodes) {
512
- const { packagePath, files, updatedManifest, pkgName } = node
491
+ const { packagePath, files, updatedManifest, originalPath } = node
513
492
  const { name, version } = updatedManifest
514
493
 
494
+ const { modulePath, idPath } = buildDependencyPackagePath(
495
+ project.getRootDir(),
496
+ name,
497
+ version,
498
+ originalPath
499
+ )
515
500
  for (const file of files) {
516
501
  const fileContent = fs.readFileSync(pathModule.join(packagePath, file)).toString('utf-8')
517
502
  if (/(.js|.cjs|.mjs)$/.test(pathModule.extname(file))) {
@@ -522,15 +507,16 @@ export const ServerModulePlugin = Plugin.create({
522
507
  }
523
508
  }
524
509
 
525
- const importerPath = importerMap[`${pkgName}@${version}`]
526
510
  modules.push({
527
- id: `${name}@${version}/${file}`,
511
+ id: NowConfig.legacyPackageResolution(config)
512
+ ? `${name}@${version}/${file}`
513
+ : `${idPath}@${version}/${file}`,
528
514
  path: getModuleDependencyPath(config, {
529
515
  name,
530
516
  file,
531
517
  version,
532
518
  packageJson,
533
- ...(importerPath ? { importerPath } : {}),
519
+ modulePath,
534
520
  }),
535
521
  content: fileContent,
536
522
  })
@@ -539,21 +525,22 @@ export const ServerModulePlugin = Plugin.create({
539
525
 
540
526
  const records: Record[] = []
541
527
  for (const m of modules) {
542
- records.push(
543
- await factory.createRecord({
544
- source: shape,
545
- table: 'sys_module',
546
- explicitId: m.id,
547
- properties: {
548
- path: m.path,
549
- content: Shape.from(shape, sanitizeModuleContent(m.content))
550
- .asString()
551
- .withContentType('cdata'),
552
- external_source: true,
553
- sys_name: m.path,
554
- },
555
- })
556
- )
528
+ const record = await factory.createRecord({
529
+ source: shape,
530
+ table: 'sys_module',
531
+ explicitId: m.id,
532
+ properties: {
533
+ path: m.path,
534
+ content: Shape.from(shape, sanitizeModuleContent(m.content))
535
+ .asString()
536
+ .withContentType('cdata'),
537
+ external_source: !isTrusted,
538
+ sys_name: m.path,
539
+ },
540
+ })
541
+ // Track external module IDs for SBOM generation
542
+ EXTERNAL_MODULE_IDS.add(record.getId().getValue())
543
+ records.push(record)
557
544
  }
558
545
 
559
546
  const [first, ...rest] = records
@@ -599,3 +586,42 @@ export const ServerModulePlugin = Plugin.create({
599
586
  },
600
587
  ],
601
588
  })
589
+
590
+ /**
591
+ * Builds a relative dependency package path from an absolute path.
592
+ * Handles special cases for monorepo dependencies and pnpm-style paths.
593
+ *
594
+ * @param rootDir - The project root directory
595
+ * @param name - The package name
596
+ * @param version - The package version
597
+ * @param path - The absolute path to the package (optional)
598
+ * @returns Relative path suitable for module resolution
599
+ */
600
+ function buildDependencyPackagePath(
601
+ rootDir: string,
602
+ name: string,
603
+ version: string,
604
+ path?: string
605
+ ): {
606
+ modulePath: string
607
+ idPath: string
608
+ } {
609
+ let relative = pathModule.relative(rootDir, path ?? '')
610
+ const isMonorepoDependency = relative.includes(`../`)
611
+ const isPnpm = relative.includes('.pnpm')
612
+ if (isMonorepoDependency) {
613
+ // Treat monorepo node_modules as if they are inside app node_modules
614
+ relative = relative.replaceAll('../', '').replaceAll('+', '/')
615
+ }
616
+ if (isPnpm) {
617
+ // Do our best to turn this pnpm path into an npm path
618
+ relative = relative.replaceAll('+', '/').replaceAll(`node_modules/.pnpm/${name}@${version}/`, '')
619
+ }
620
+
621
+ // IDs will resemble the legacy paths and share sys_ids if possible
622
+ const idPath = relative.replaceAll('node_modules/', '').replaceAll('.pnpm/', '')
623
+ return {
624
+ modulePath: relative,
625
+ idPath,
626
+ }
627
+ }
@@ -0,0 +1,140 @@
1
+ import { CallExpressionShape, Plugin, type PropertyAccessShape } from '@servicenow/sdk-build-core'
2
+ import { NowIdShape } from '../now-id-plugin'
3
+ import {
4
+ getUITypeFromId,
5
+ getUITypeId,
6
+ APPLIES_TO_CATALOG_ITEM,
7
+ createScript,
8
+ createVariablePropertyAccess,
9
+ getTargetRecord,
10
+ resolveCatalogReferences,
11
+ resolveAndValidateVariableId,
12
+ } from './utils'
13
+ import { validateCatalogItemVariableSetExclusivity } from './service-catalog-diagnostics'
14
+
15
+ export const CatalogClientScriptPlugin = Plugin.create({
16
+ name: 'CatalogClientScriptPlugin',
17
+ records: {
18
+ catalog_script_client: {
19
+ async toShape(record, { database, transform }) {
20
+ let propertyAccess: PropertyAccessShape | string | undefined
21
+ if (
22
+ record.get('type').asString().getValue() === 'onChange' &&
23
+ !record.get('cat_variable')?.ifString()?.isEmpty()
24
+ ) {
25
+ const variableId = record.get('cat_variable').asString()?.getValue()?.replace('IO:', '')
26
+ const varRecord = database.get('item_option_new', variableId)
27
+
28
+ if (varRecord?.isRecord()) {
29
+ const appliesToRecord = getTargetRecord(record, database)
30
+ propertyAccess =
31
+ (appliesToRecord?.isRecord() &&
32
+ createVariablePropertyAccess(varRecord, record, appliesToRecord)) ||
33
+ variableId
34
+ } else {
35
+ propertyAccess = variableId
36
+ }
37
+ }
38
+
39
+ const { catalogItemReference, variableSetReference } = resolveCatalogReferences(record, database)
40
+ const script = await createScript(record, record.get('script'), transform, 'script')
41
+
42
+ return {
43
+ success: true,
44
+ value: new CallExpressionShape({
45
+ source: record,
46
+ callee: 'CatalogClientScript',
47
+ args: [
48
+ record.transform(({ $ }) => ({
49
+ $id: $.val(NowIdShape.from(record)),
50
+ name: $,
51
+ script: $.val(script).def(''),
52
+ global: $.toBoolean().def(true),
53
+ active: $.toBoolean().def(true),
54
+ type: $,
55
+ uiType: $.from('ui_type')
56
+ .map((v) =>
57
+ v.ifString()?.isEmpty() ? undefined : getUITypeFromId(v.toNumber()?.getValue())
58
+ )
59
+ .def('desktop'),
60
+ catalogItem: $.val(catalogItemReference).def(''),
61
+ variableName: $.val(propertyAccess).def(''),
62
+ variableSet: $.val(variableSetReference).def(''),
63
+ appliesTo: $.from('applies_to').def(APPLIES_TO_CATALOG_ITEM),
64
+ appliesOnCatalogItemView: $.from('applies_catalog').toBoolean().def(true),
65
+ appliesOnRequestedItems: $.from('applies_req_item').toBoolean().def(false),
66
+ appliesOnCatalogTasks: $.from('applies_sc_task').toBoolean().def(false),
67
+ appliesOnTargetRecord: $.from('applies_target_record').toBoolean().def(false),
68
+ vaSupported: $.from('va_supported').toBoolean().def(false),
69
+ publishedRef: $.from('published_ref').def(''),
70
+ isolateScript: $.from('isolate_script').toBoolean().def(true),
71
+ })),
72
+ ],
73
+ }),
74
+ }
75
+ },
76
+ },
77
+ },
78
+ shapes: [
79
+ {
80
+ shape: CallExpressionShape,
81
+ fileTypes: ['fluent'],
82
+ async toRecord(callExpression, { diagnostics, factory }) {
83
+ if (callExpression.getCallee() !== 'CatalogClientScript') {
84
+ return { success: false }
85
+ }
86
+ const catalogClientScriptArgs = callExpression.getArgument(0).asObject()
87
+
88
+ // Validate catalogItem and variableSet are mutually exclusive
89
+ validateCatalogItemVariableSetExclusivity(catalogClientScriptArgs, diagnostics, 'CatalogClientScript')
90
+
91
+ // Check that uiType is 'onChange' only
92
+ const typeValue = catalogClientScriptArgs.get('type')?.toString()?.getValue()
93
+ // Handle variableName - extract name and ID from PropertyAccessShape
94
+
95
+ let variableId: string | undefined
96
+ const appliedTo: 'set' | 'item' =
97
+ catalogClientScriptArgs.get('appliesTo')?.toString()?.getValue() === 'set'
98
+ ? 'set'
99
+ : APPLIES_TO_CATALOG_ITEM
100
+ if (typeValue && typeValue === 'onChange') {
101
+ variableId = resolveAndValidateVariableId(
102
+ catalogClientScriptArgs.get('variableName', false),
103
+ appliedTo,
104
+ catalogClientScriptArgs.get('variableSet', false),
105
+ catalogClientScriptArgs.get('catalogItem', false),
106
+ diagnostics
107
+ )
108
+ }
109
+
110
+ const record = await factory.createRecord({
111
+ source: callExpression,
112
+ table: 'catalog_script_client',
113
+ explicitId: catalogClientScriptArgs.get('$id'),
114
+ properties: catalogClientScriptArgs.transform(({ $ }) => ({
115
+ name: $,
116
+ active: $.def(true),
117
+ global: $.def(true),
118
+ script: $.toCdata(),
119
+ type: $,
120
+ applies_to: $.from('appliesTo').def(APPLIES_TO_CATALOG_ITEM),
121
+ cat_item: $.from('catalogItem').def(''),
122
+ variable_set: $.from('variableSet').def(''),
123
+ cat_variable: $.val(variableId).def(''),
124
+ applies_catalog: $.from('appliesOnCatalogItemView').def(true),
125
+ applies_req_item: $.from('appliesOnRequestedItems').def(false),
126
+ applies_sc_task: $.from('appliesOnCatalogTasks').def(false),
127
+ applies_target_record: $.from('appliesOnTargetRecord').def(false),
128
+ isolate_script: $.from('isolateScript').def(true),
129
+ ui_type: $.from('uiType')
130
+ .map((v) => (v.isString() && !v.isEmpty() ? getUITypeId(v.getValue()) : undefined))
131
+ .def(0),
132
+ va_supported: $.from('vaSupported').toBoolean().def(false),
133
+ published_ref: $.from('publishedRef').def(''),
134
+ })),
135
+ })
136
+ return { success: true, value: record }
137
+ },
138
+ },
139
+ ],
140
+ })