@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,331 @@
1
+ /**
2
+ * SLA Plugin Validation Functions
3
+ *
4
+ * This module contains validation functions that enforce conditional field requirements
5
+ * for SLA definitions. Fields may be mandatory, optional, or restricted depending on
6
+ * the values of control fields.
7
+ *
8
+ * @see ./SLA-VALIDATION-BEHAVIORS.md for detailed documentation of all 11 validation behaviors
9
+ */
10
+
11
+ import type { Diagnostics, ObjectShape } from '@servicenow/sdk-build-core'
12
+
13
+ export const DEFAULT_WHEN_TO_RESUME = 'on_condition'
14
+ export const DEFAULT_WHEN_TO_CANCEL = 'on_condition'
15
+ export const DEFAULT_TIMEZONE_SOURCE = 'task.caller_id.time_zone'
16
+ export const DEFAULT_RETROACTIVE_PAUSE = true
17
+ export const DEFAULT_NO_SCHEDULE_ID = '38fa64edc0a8016400f4a5724b0434b8'
18
+
19
+ export const ERROR_MESSAGES = {
20
+ MANDATORY_FIELD: (field: string, reason: string) => `Field '${field}' is required ${reason}`,
21
+
22
+ RESTRICTED_FIELD: (field: string, reason: string) =>
23
+ `Field '${field}' cannot be specified ${reason}. Remove this field from your SLA definition.`,
24
+
25
+ RESTRICTED_WITH_DEFAULT: (field: string, reason: string, defaultValue: unknown) =>
26
+ `Field '${field}' cannot be specified ${reason}. The default value '${defaultValue}' will be used automatically.`,
27
+
28
+ WARNING_FIELD_PERSISTENCE: (field: string, reason: string) =>
29
+ `Field '${field}' is restricted ${reason}. If this value came from an existing SLA definition, it will be preserved but cannot be modified. If you're creating a new SLA, remove this field.`,
30
+ }
31
+
32
+ /**
33
+ * Validates user-specified duration fields (Behavior 1)
34
+ */
35
+ export function validateUserSpecifiedDuration(config: ObjectShape, diagnostics: Diagnostics) {
36
+ const duration = config.get('duration')
37
+
38
+ // Duration is mandatory when durationType is empty/"User specified"
39
+ if (!duration || duration.isUndefined()) {
40
+ diagnostics.error(
41
+ config,
42
+ ERROR_MESSAGES.MANDATORY_FIELD('duration', 'when durationType is empty (user specified duration)')
43
+ )
44
+ }
45
+ // Note: Schedule validation is handled in validateSlaDefinitionSchedule based on scheduleSource
46
+ }
47
+
48
+ /**
49
+ * Validates relative duration restrictions (Behavior 2)
50
+ */
51
+ export function validateRelativeDuration(
52
+ config: ObjectShape,
53
+ conditions: ObjectShape | undefined,
54
+ diagnostics: Diagnostics
55
+ ) {
56
+ // When durationType is a relative duration, duration, conditions.pause, conditions.resume, and whenTo.resume
57
+ // are restricted fields. Existing values from XML are preserved (pass-through).
58
+ // We issue a warning to inform the user these fields are managed by the relative duration.
59
+ const duration = config.get('duration')
60
+ const pauseCondition = conditions?.get('pause')
61
+ const resumeCondition = conditions?.get('resume')
62
+ const whenTo = config.get('whenTo')?.ifDefined()?.asObject()
63
+ const whenToResume = whenTo?.get('resume')
64
+
65
+ // duration field is ignored when using relative duration
66
+ if (duration && !duration.isUndefined()) {
67
+ diagnostics.hint(
68
+ duration,
69
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('duration', 'when durationType is a relative duration')
70
+ )
71
+ }
72
+
73
+ if (pauseCondition && !pauseCondition.isUndefined()) {
74
+ diagnostics.hint(
75
+ pauseCondition,
76
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('conditions.pause', 'when durationType is a relative duration')
77
+ )
78
+ }
79
+
80
+ if (resumeCondition && !resumeCondition.isUndefined()) {
81
+ diagnostics.hint(
82
+ resumeCondition,
83
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('conditions.resume', 'when durationType is a relative duration')
84
+ )
85
+ }
86
+
87
+ if (whenToResume && !whenToResume.isUndefined()) {
88
+ diagnostics.hint(
89
+ whenToResume,
90
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('whenTo.resume', 'when durationType is a relative duration')
91
+ )
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Validates retroactive start requirements (Behaviors 6 & 8)
97
+ */
98
+ export function validateRetroactiveStart(
99
+ retroactive: ObjectShape,
100
+ isUserSpecifiedDuration: boolean,
101
+ diagnostics: Diagnostics
102
+ ) {
103
+ const setStartTo = retroactive.get('setStartTo')
104
+ const retroactivePause = retroactive.get('pause')
105
+
106
+ // setStartTo is mandatory when retroactive.start is true
107
+ const setStartToValue = setStartTo?.ifString()?.getValue()
108
+ if (!setStartToValue) {
109
+ diagnostics.error(
110
+ retroactive,
111
+ ERROR_MESSAGES.MANDATORY_FIELD('retroactive.setStartTo', 'when retroactive.start is true')
112
+ )
113
+ }
114
+
115
+ // Behavior 8: retroactive.start + relative duration restricts retroactive.pause
116
+ // Existing values from XML are preserved (pass-through) with a warning.
117
+ if (!isUserSpecifiedDuration && retroactivePause && !retroactivePause.isUndefined()) {
118
+ diagnostics.hint(
119
+ retroactivePause,
120
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE(
121
+ 'retroactive.pause',
122
+ 'when retroactive.start is true and durationType is a relative duration'
123
+ )
124
+ )
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Validates that retroactive.pause and retroactive.setStartTo are not set when retroactive.start is false (Behavior 7)
130
+ */
131
+ export function validateRetroactiveFieldsWithoutStart(retroactive: ObjectShape | undefined, diagnostics: Diagnostics) {
132
+ if (!retroactive) {
133
+ return
134
+ }
135
+
136
+ const setStartTo = retroactive.get('setStartTo')
137
+ const retroactivePause = retroactive.get('pause')
138
+
139
+ // setStartTo requires retroactive.start to be true (warning for existing values)
140
+ if (setStartTo && !setStartTo.isUndefined()) {
141
+ const value = setStartTo.ifString()?.getValue()
142
+ if (value) {
143
+ diagnostics.hint(
144
+ setStartTo,
145
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('retroactive.setStartTo', 'unless retroactive.start is true')
146
+ )
147
+ }
148
+ }
149
+
150
+ // retroactive.pause requires retroactive.start to be true (warning for existing values)
151
+ if (retroactivePause && !retroactivePause.isUndefined()) {
152
+ const value = retroactivePause.ifBoolean()?.getValue()
153
+ if (value !== undefined) {
154
+ diagnostics.hint(
155
+ retroactivePause,
156
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('retroactive.pause', 'unless retroactive.start is true')
157
+ )
158
+ }
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Validates no_schedule restrictions (Behavior 4)
164
+ */
165
+ export function validateNoScheduleRestrictions(config: ObjectShape, diagnostics: Diagnostics) {
166
+ const schedule = config.get('schedule')
167
+ const timezoneSource = config.get('timezoneSource')
168
+ const timezone = config.get('timezone')
169
+ const scheduleSourceField = config.get('scheduleSourceField')
170
+
171
+ // Schedule field: warn if provided, since default is forced
172
+ if (schedule && !schedule.isUndefined()) {
173
+ const value = schedule.ifString()?.getValue()
174
+ if (value) {
175
+ diagnostics.hint(
176
+ schedule,
177
+ ERROR_MESSAGES.RESTRICTED_WITH_DEFAULT(
178
+ 'schedule',
179
+ 'when scheduleSource is "no_schedule"',
180
+ DEFAULT_NO_SCHEDULE_ID
181
+ )
182
+ )
183
+ }
184
+ }
185
+
186
+ // timezoneSource: existing values are preserved with a warning
187
+ if (timezoneSource && !timezoneSource.isUndefined()) {
188
+ const value = timezoneSource.ifString()?.getValue()
189
+ if (value && value !== DEFAULT_TIMEZONE_SOURCE) {
190
+ diagnostics.hint(
191
+ timezoneSource,
192
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('timezoneSource', 'when scheduleSource is "no_schedule"')
193
+ )
194
+ }
195
+ }
196
+
197
+ // timezone: existing values are preserved with a warning
198
+ if (timezone && !timezone.isUndefined()) {
199
+ const value = timezone.ifString()?.getValue()
200
+ if (value) {
201
+ diagnostics.hint(
202
+ timezone,
203
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('timezone', 'when scheduleSource is "no_schedule"')
204
+ )
205
+ }
206
+ }
207
+
208
+ // scheduleSourceField: warn since it doesn't apply to no_schedule
209
+ if (scheduleSourceField && !scheduleSourceField.isUndefined()) {
210
+ const value = scheduleSourceField.ifString()?.getValue()
211
+ if (value) {
212
+ diagnostics.hint(
213
+ scheduleSourceField,
214
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('scheduleSourceField', 'when scheduleSource is "no_schedule"')
215
+ )
216
+ }
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Validates task_field schedule requirements (Behavior 5)
222
+ */
223
+ export function validateTaskFieldSchedule(config: ObjectShape, diagnostics: Diagnostics) {
224
+ const schedule = config.get('schedule')
225
+ const scheduleSourceField = config.get('scheduleSourceField')
226
+ const duration = config.get('duration')
227
+
228
+ // schedule: warn since it doesn't apply when using task_field
229
+ if (schedule && !schedule.isUndefined()) {
230
+ const value = schedule.ifString()?.getValue()
231
+ if (value) {
232
+ diagnostics.hint(
233
+ schedule,
234
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('schedule', 'when scheduleSource is "task_field"')
235
+ )
236
+ }
237
+ }
238
+
239
+ // duration: warn since it doesn't apply when using task_field
240
+ if (duration && !duration.isUndefined()) {
241
+ diagnostics.hint(
242
+ duration,
243
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('duration', 'when scheduleSource is "task_field"')
244
+ )
245
+ }
246
+
247
+ if (!scheduleSourceField || scheduleSourceField.isUndefined()) {
248
+ diagnostics.error(
249
+ config,
250
+ ERROR_MESSAGES.MANDATORY_FIELD('scheduleSourceField', 'when scheduleSource is "task_field"')
251
+ )
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Validates sla_definition schedule requirements (Behavior 3)
257
+ */
258
+ export function validateSlaDefinitionSchedule(config: ObjectShape, diagnostics: Diagnostics) {
259
+ const schedule = config.get('schedule')
260
+ const scheduleValue = schedule?.ifString()?.getValue()
261
+
262
+ // Check for undefined, null, or empty string
263
+ if (!schedule || schedule.isUndefined() || !scheduleValue) {
264
+ diagnostics.error(config, ERROR_MESSAGES.MANDATORY_FIELD('schedule', 'when scheduleSource is "sla_definition"'))
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Validates timezone source restrictions (Behavior 9)
270
+ */
271
+ export function validateTimezoneSource(
272
+ config: ObjectShape,
273
+ timezoneSource: string | undefined,
274
+ diagnostics: Diagnostics
275
+ ) {
276
+ const timezone = config.get('timezone')
277
+
278
+ // Only allow timezone field when timezoneSource is 'sla.timezone'
279
+ // Existing values from XML are preserved (pass-through) with a warning.
280
+ if (timezoneSource !== 'sla.timezone' && timezone && !timezone.isUndefined()) {
281
+ const currentValue = timezone.ifString()?.getValue()
282
+ if (currentValue) {
283
+ diagnostics.hint(
284
+ timezone,
285
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('timezone', 'unless timezoneSource is "sla.timezone"')
286
+ )
287
+ }
288
+ }
289
+ }
290
+
291
+ /**
292
+ * Validates no_match resume restrictions (Behavior 10)
293
+ */
294
+ export function validateNoMatchResume(conditions: ObjectShape | undefined, diagnostics: Diagnostics) {
295
+ const resumeCondition = conditions?.get('resume')
296
+
297
+ // When whenToResume is "no_match", conditions.resume is restricted.
298
+ // Existing values from XML are preserved (pass-through) with a warning.
299
+ if (resumeCondition && !resumeCondition.isUndefined()) {
300
+ const currentValue = resumeCondition.ifString()?.getValue()
301
+ if (currentValue) {
302
+ diagnostics.hint(
303
+ resumeCondition,
304
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('conditions.resume', 'when whenToResume is "no_match"')
305
+ )
306
+ }
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Validates cancel condition restrictions (Behavior 11)
312
+ */
313
+ export function validateCancelCondition(
314
+ whenToCancel: string | undefined,
315
+ conditions: ObjectShape | undefined,
316
+ diagnostics: Diagnostics
317
+ ) {
318
+ const cancelCondition = conditions?.get('cancel')
319
+
320
+ // Only allow conditions.cancel when whenToCancel is 'on_condition'
321
+ // Existing values from XML are preserved (pass-through) with a warning.
322
+ if (whenToCancel !== 'on_condition' && cancelCondition && !cancelCondition.isUndefined()) {
323
+ const currentValue = cancelCondition.ifString()?.getValue()
324
+ if (currentValue) {
325
+ diagnostics.hint(
326
+ cancelCondition,
327
+ ERROR_MESSAGES.WARNING_FIELD_PERSISTENCE('conditions.cancel', 'unless whenToCancel is "on_condition"')
328
+ )
329
+ }
330
+ }
331
+ }
@@ -0,0 +1,358 @@
1
+ import { CallExpressionShape, Plugin, DurationShape } from '@servicenow/sdk-build-core'
2
+ import { NowIdShape } from './now-id-plugin'
3
+ import {
4
+ validateUserSpecifiedDuration,
5
+ validateRelativeDuration,
6
+ validateRetroactiveStart,
7
+ validateRetroactiveFieldsWithoutStart,
8
+ validateNoScheduleRestrictions,
9
+ validateTaskFieldSchedule,
10
+ validateSlaDefinitionSchedule,
11
+ validateTimezoneSource,
12
+ validateNoMatchResume,
13
+ validateCancelCondition,
14
+ DEFAULT_WHEN_TO_RESUME,
15
+ DEFAULT_WHEN_TO_CANCEL,
16
+ DEFAULT_TIMEZONE_SOURCE,
17
+ DEFAULT_RETROACTIVE_PAUSE,
18
+ DEFAULT_NO_SCHEDULE_ID,
19
+ } from './sla/sla-validators'
20
+
21
+ const DEFAULT_SLA_FLOW = '828f267973333300e289235f04f6a7a3'
22
+ const DEFAULT_COLLECTION = 'incident'
23
+ const DEFAULT_TYPE = 'SLA'
24
+ const DEFAULT_ACTIVE = true
25
+ const DEFAULT_ADV_CONDITION_TYPE = 'none'
26
+ const DEFAULT_SCHEDULE_SOURCE = 'sla_definition'
27
+ const DEFAULT_RELATIVE_DURATION_WORKS_ON = 'Task record'
28
+ const DEFAULT_RESET_ACTION = 'cancel'
29
+ const DEFAULT_RETROACTIVE = false
30
+ const DEFAULT_ENABLE_LOGGING = false
31
+ const DEFAULT_SYS_DOMAIN_PATH = '/'
32
+ const DEFAULT_DURATION_ON_PLATFORM = '1970-01-01 00:00:00'
33
+
34
+ /**
35
+ * See ./sla/sla-validators.ts for validation behavior documentation.
36
+ */
37
+ export const SLAPlugin = Plugin.create({
38
+ name: 'SLAPlugin',
39
+
40
+ records: {
41
+ contract_sla: {
42
+ async toShape(record) {
43
+ return {
44
+ success: true,
45
+ value: new CallExpressionShape({
46
+ source: record,
47
+ callee: 'Sla',
48
+ args: [
49
+ record.transform(({ $ }) => ({
50
+ $id: $.val(NowIdShape.from(record)),
51
+ name: $.map((v) => v.ifString()?.ifNotEmpty()?.getValue()),
52
+ table: $.from('collection'),
53
+ duration: $.from('duration').map((v) => {
54
+ const stringShape = v.ifString()?.ifNotEmpty()
55
+ if (!stringShape) {
56
+ return DurationShape.zero(record)
57
+ }
58
+ const value = stringShape.getValue()
59
+ if (value === DEFAULT_DURATION_ON_PLATFORM) {
60
+ return DurationShape.zero(record)
61
+ }
62
+ return DurationShape.from(record, stringShape)
63
+ }),
64
+ // Return empty string when scheduleSource is 'no_schedule'
65
+ schedule: $.from('schedule', 'schedule_source').map((schedule, schedule_source) => {
66
+ const scheduleSourceValue = schedule_source.ifString()?.getValue()
67
+ if (scheduleSourceValue === 'no_schedule') {
68
+ return ''
69
+ }
70
+ return schedule.ifString()?.ifNotEmpty()?.getValue() ?? ''
71
+ }),
72
+
73
+ type: $.def(DEFAULT_TYPE),
74
+ active: $.toBoolean().def(DEFAULT_ACTIVE),
75
+ advancedConditionType: $.from('adv_condition_type').def(DEFAULT_ADV_CONDITION_TYPE),
76
+
77
+ // Duration & Schedule
78
+ durationType: $.from('duration_type').def(''),
79
+ scheduleSource: $.from('schedule_source').def(DEFAULT_SCHEDULE_SOURCE),
80
+ scheduleSourceField: $.from('schedule_source_field').def(''),
81
+ relativeDurationWorksOn: $.from('relative_duration_works_on').def(
82
+ DEFAULT_RELATIVE_DURATION_WORKS_ON
83
+ ),
84
+
85
+ // Conditions
86
+ conditions: $.from(
87
+ 'start_condition',
88
+ 'stop_condition',
89
+ 'pause_condition',
90
+ 'resume_condition',
91
+ 'reset_condition',
92
+ 'cancel_condition'
93
+ ).map(
94
+ (
95
+ start_condition,
96
+ stop_condition,
97
+ pause_condition,
98
+ resume_condition,
99
+ reset_condition,
100
+ cancel_condition
101
+ ) => {
102
+ const conditions: Record<string, string> = {}
103
+
104
+ const startStr = start_condition.ifString()?.ifNotEmpty()?.getValue()
105
+ if (startStr) {
106
+ conditions['start'] = startStr
107
+ }
108
+
109
+ const stopStr = stop_condition.ifString()?.ifNotEmpty()?.getValue()
110
+ if (stopStr) {
111
+ conditions['stop'] = stopStr
112
+ }
113
+
114
+ const pauseStr = pause_condition.ifString()?.ifNotEmpty()?.getValue()
115
+ if (pauseStr) {
116
+ conditions['pause'] = pauseStr
117
+ }
118
+
119
+ const resumeStr = resume_condition.ifString()?.ifNotEmpty()?.getValue()
120
+ if (resumeStr) {
121
+ conditions['resume'] = resumeStr
122
+ }
123
+
124
+ const resetStr = reset_condition.ifString()?.ifNotEmpty()?.getValue()
125
+ if (resetStr) {
126
+ conditions['reset'] = resetStr
127
+ }
128
+
129
+ const cancelStr = cancel_condition.ifString()?.ifNotEmpty()?.getValue()
130
+ if (cancelStr) {
131
+ conditions['cancel'] = cancelStr
132
+ }
133
+
134
+ return Object.keys(conditions).length > 0 ? conditions : undefined
135
+ }
136
+ ),
137
+
138
+ // Condition Behavior
139
+ conditionType: $.from('condition_class').def(''),
140
+ resetAction: $.from('reset_action').def(DEFAULT_RESET_ACTION),
141
+ whenTo: $.from('when_to_resume', 'when_to_cancel').map(
142
+ (when_to_resume, when_to_cancel) => {
143
+ const resumeValue = when_to_resume.ifString()?.getValue()
144
+ const cancelValue = when_to_cancel.ifString()?.getValue()
145
+ return {
146
+ resume: resumeValue || DEFAULT_WHEN_TO_RESUME,
147
+ cancel: cancelValue || DEFAULT_WHEN_TO_CANCEL,
148
+ }
149
+ }
150
+ ),
151
+
152
+ // Retroactive
153
+ retroactive: $.from('retroactive', 'retroactive_pause', 'set_start_to').map(
154
+ (retroactive, retroactive_pause, set_start_to) => {
155
+ const startValue = retroactive.ifBoolean()?.getValue() ?? DEFAULT_RETROACTIVE
156
+ const pauseValue = retroactive_pause.ifBoolean()?.getValue()
157
+ const setStartToValue = set_start_to.ifString()?.ifNotEmpty()?.getValue()
158
+
159
+ const result: { start: boolean; pause?: boolean; setStartTo?: string } = {
160
+ start: startValue,
161
+ }
162
+
163
+ // Only include pause when start is true (per Behavior 6/7)
164
+ if (startValue) {
165
+ result.pause = pauseValue ?? DEFAULT_RETROACTIVE_PAUSE
166
+ }
167
+
168
+ // Only include setStartTo if it has a valid value
169
+ if (setStartToValue) {
170
+ result.setStartTo = setStartToValue
171
+ }
172
+
173
+ return result
174
+ }
175
+ ),
176
+
177
+ // References
178
+ overrides: $.from('sys_overrides').def(''),
179
+ workflow: $.def(''),
180
+ flow: $.def(''),
181
+ vendor: $.def(''),
182
+
183
+ // Time Zones
184
+ timezone: $.def(''),
185
+ timezoneSource: $.from('timezone_source').def(DEFAULT_TIMEZONE_SOURCE),
186
+
187
+ // Metadata
188
+ enableLogging: $.from('enable_logging').toBoolean().def(DEFAULT_ENABLE_LOGGING),
189
+ target: $.def(''),
190
+
191
+ // Domain
192
+ domainPath: $.from('sys_domain_path').def(DEFAULT_SYS_DOMAIN_PATH),
193
+ })),
194
+ ],
195
+ }),
196
+ }
197
+ },
198
+ },
199
+ },
200
+
201
+ shapes: [
202
+ {
203
+ shape: CallExpressionShape,
204
+ fileTypes: ['fluent'],
205
+ async toRecord(callExpression, { factory, diagnostics }) {
206
+ if (callExpression.getCallee() !== 'Sla') {
207
+ return { success: false }
208
+ }
209
+
210
+ const config = callExpression.getArgument(0).asObject()
211
+
212
+ // Extract Control Fields
213
+ const durationType = config.get('durationType')
214
+ const durationTypeValue = durationType?.ifString()?.getValue()
215
+ const isUserSpecifiedOrEmptyDuration = !durationTypeValue || durationTypeValue === ''
216
+
217
+ const scheduleSource = config.get('scheduleSource')
218
+ const scheduleSourceValue = scheduleSource?.ifString()?.getValue() || DEFAULT_SCHEDULE_SOURCE
219
+
220
+ const retroactive = config.get('retroactive')?.ifDefined()?.asObject()
221
+ const retroactiveStartValue = retroactive?.get('start')?.ifBoolean()?.getValue() || false
222
+
223
+ const whenTo = config.get('whenTo')?.ifDefined()?.asObject()
224
+ const whenToResumeValue = whenTo?.get('resume')?.ifString()?.getValue() || DEFAULT_WHEN_TO_RESUME
225
+ const whenToCancelValue = whenTo?.get('cancel')?.ifString()?.getValue() || DEFAULT_WHEN_TO_CANCEL
226
+
227
+ const timezoneSource = config.get('timezoneSource')
228
+ const timezoneSourceValue = timezoneSource?.ifString()?.getValue() || DEFAULT_TIMEZONE_SOURCE
229
+
230
+ // Extract conditions object
231
+ const conditions = config.get('conditions').ifDefined()?.asObject()
232
+
233
+ if (isUserSpecifiedOrEmptyDuration) {
234
+ // Behavior 1: User specified duration
235
+ // Validate duration field uses Duration() helper (only when duration is expected)
236
+ const duration = config.get('duration')
237
+ if (duration && duration.isDefined()) {
238
+ if (!(duration instanceof CallExpressionShape) || duration.getCallee() !== 'Duration') {
239
+ diagnostics.error(duration, "SLA 'duration' field must use the Duration() helper function")
240
+ }
241
+ }
242
+ validateUserSpecifiedDuration(config, diagnostics)
243
+ } else {
244
+ // Behavior 2: Relative duration
245
+ validateRelativeDuration(config, conditions, diagnostics)
246
+ }
247
+
248
+ // Schedule Source Validations
249
+ if (scheduleSourceValue === 'no_schedule') {
250
+ // Behavior 5: No schedule
251
+ validateNoScheduleRestrictions(config, diagnostics)
252
+ } else if (scheduleSourceValue === 'task_field') {
253
+ // Behavior 6: Task field schedule
254
+ validateTaskFieldSchedule(config, diagnostics)
255
+ } else if (scheduleSourceValue === 'sla_definition') {
256
+ // Behavior 7: SLA definition schedule (default)
257
+ validateSlaDefinitionSchedule(config, diagnostics)
258
+ }
259
+
260
+ // Condition Field Validations
261
+ // Behavior 8: Timezone source
262
+ validateTimezoneSource(config, timezoneSourceValue, diagnostics)
263
+
264
+ // Behavior 9: When to resume = "no_match"
265
+ if (whenToResumeValue === 'no_match') {
266
+ validateNoMatchResume(conditions, diagnostics)
267
+ }
268
+
269
+ // Behavior 10: When to cancel validation
270
+ validateCancelCondition(whenToCancelValue, conditions, diagnostics)
271
+
272
+ // Retroactive Validations
273
+ if (retroactiveStartValue && retroactive) {
274
+ // Behaviors 6 & 8: Retroactive start validations
275
+ validateRetroactiveStart(retroactive, isUserSpecifiedOrEmptyDuration, diagnostics)
276
+ } else {
277
+ // Behavior 7: Validate that retroactive-dependent fields are not set when retroactive.start is false
278
+ validateRetroactiveFieldsWithoutStart(retroactive, diagnostics)
279
+ }
280
+
281
+ return {
282
+ success: true,
283
+ value: await factory.createRecord({
284
+ source: callExpression,
285
+ table: 'contract_sla',
286
+ explicitId: config.get('$id'),
287
+ properties: config.transform(({ $ }) => ({
288
+ // Core
289
+ name: $.map((v) => v.ifString()?.ifNotEmpty()?.getValue()),
290
+ collection: $.from('table').def(DEFAULT_COLLECTION),
291
+ type: $.def(DEFAULT_TYPE),
292
+ active: $.def(DEFAULT_ACTIVE),
293
+ adv_condition_type: $.from('advancedConditionType').def(DEFAULT_ADV_CONDITION_TYPE),
294
+
295
+ // Duration & Schedule
296
+ duration: $.map((v) => v.toString()),
297
+ duration_type: $.from('durationType').toString(),
298
+ // Conditional schedule: force default when no_schedule
299
+ schedule: $.map((v) => {
300
+ if (scheduleSourceValue === 'no_schedule') {
301
+ return DEFAULT_NO_SCHEDULE_ID
302
+ }
303
+ return v.ifString()?.ifNotEmpty()?.getValue()
304
+ }),
305
+ schedule_source: $.from('scheduleSource').def(DEFAULT_SCHEDULE_SOURCE),
306
+ schedule_source_field: $.from('scheduleSourceField'),
307
+ relative_duration_works_on: $.from('relativeDurationWorksOn').def(
308
+ DEFAULT_RELATIVE_DURATION_WORKS_ON
309
+ ),
310
+
311
+ // Conditions
312
+ start_condition: $.val(conditions?.get('start')),
313
+ reset_condition: $.val(conditions?.get('reset')),
314
+ stop_condition: $.val(conditions?.get('stop')),
315
+ cancel_condition: $.val(conditions?.get('cancel')),
316
+ pause_condition: $.val(conditions?.get('pause')),
317
+ resume_condition: $.val(conditions?.get('resume')),
318
+
319
+ // Condition Behavior
320
+ condition_class: $.from('conditionType').toString(),
321
+ reset_action: $.from('resetAction').def(DEFAULT_RESET_ACTION),
322
+ when_to_resume: $.val(whenTo?.get('resume')).def(DEFAULT_WHEN_TO_RESUME),
323
+ when_to_cancel: $.val(whenTo?.get('cancel')).def(DEFAULT_WHEN_TO_CANCEL),
324
+
325
+ // Retroactive
326
+ retroactive: $.val(retroactive?.get('start')).def(DEFAULT_RETROACTIVE),
327
+ retroactive_pause: $.map(() => {
328
+ const value = retroactive?.get('pause')?.ifBoolean()?.getValue()
329
+ if (value !== undefined) {
330
+ return value
331
+ }
332
+ return isUserSpecifiedOrEmptyDuration ? DEFAULT_RETROACTIVE_PAUSE : undefined
333
+ }),
334
+ set_start_to: $.val(retroactive?.get('setStartTo')),
335
+
336
+ // References
337
+ sys_overrides: $.from('overrides'),
338
+ workflow: $,
339
+ flow: $.from('flow').def(DEFAULT_SLA_FLOW),
340
+ vendor: $,
341
+
342
+ // Time Zones
343
+ timezone: $,
344
+ timezone_source: $.from('timezoneSource').def(DEFAULT_TIMEZONE_SOURCE),
345
+
346
+ // Metadata
347
+ enable_logging: $.from('enableLogging').def(DEFAULT_ENABLE_LOGGING),
348
+ target: $,
349
+
350
+ // Domain
351
+ sys_domain_path: $.from('domainPath').def(DEFAULT_SYS_DOMAIN_PATH),
352
+ })),
353
+ }),
354
+ }
355
+ },
356
+ },
357
+ ],
358
+ })