@servicenow/sdk-build-plugins 4.1.1 → 4.3.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 (388) hide show
  1. package/dist/acl-plugin.js +22 -4
  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/application-menu-plugin.js +1 -0
  7. package/dist/application-menu-plugin.js.map +1 -1
  8. package/dist/atf/step-configs.d.ts +13 -12
  9. package/dist/atf/step-configs.js.map +1 -1
  10. package/dist/atf/test-plugin.d.ts +1 -1
  11. package/dist/atf/test-plugin.js +13 -7
  12. package/dist/atf/test-plugin.js.map +1 -1
  13. package/dist/basic-syntax-plugin.js +58 -14
  14. package/dist/basic-syntax-plugin.js.map +1 -1
  15. package/dist/business-rule-plugin.js +1 -0
  16. package/dist/business-rule-plugin.js.map +1 -1
  17. package/dist/call-expression-plugin.js +1 -107
  18. package/dist/call-expression-plugin.js.map +1 -1
  19. package/dist/claims-plugin.js +1 -1
  20. package/dist/claims-plugin.js.map +1 -1
  21. package/dist/client-script-plugin.js +5 -17
  22. package/dist/client-script-plugin.js.map +1 -1
  23. package/dist/column/column-helper.d.ts +1 -1
  24. package/dist/column/column-helper.js +46 -2
  25. package/dist/column/column-helper.js.map +1 -1
  26. package/dist/column/column-to-record.js +6 -4
  27. package/dist/column/column-to-record.js.map +1 -1
  28. package/dist/column-plugin.js +107 -28
  29. package/dist/column-plugin.js.map +1 -1
  30. package/dist/dashboard/dashboard-component-property-defaults.d.ts +152 -0
  31. package/dist/dashboard/dashboard-component-property-defaults.js +264 -0
  32. package/dist/dashboard/dashboard-component-property-defaults.js.map +1 -0
  33. package/dist/dashboard/dashboard-component-resolver.d.ts +13 -0
  34. package/dist/dashboard/dashboard-component-resolver.js +69 -0
  35. package/dist/dashboard/dashboard-component-resolver.js.map +1 -0
  36. package/dist/dashboard/dashboard-plugin.d.ts +12 -0
  37. package/dist/dashboard/dashboard-plugin.js +397 -0
  38. package/dist/dashboard/dashboard-plugin.js.map +1 -0
  39. package/dist/data-plugin.d.ts +6 -0
  40. package/dist/data-plugin.js +156 -0
  41. package/dist/data-plugin.js.map +1 -0
  42. package/dist/email-notification-plugin.d.ts +2 -0
  43. package/dist/email-notification-plugin.js +541 -0
  44. package/dist/email-notification-plugin.js.map +1 -0
  45. package/dist/flow/constants/flow-plugin-constants.d.ts +58 -0
  46. package/dist/flow/constants/flow-plugin-constants.js +70 -0
  47. package/dist/flow/constants/flow-plugin-constants.js.map +1 -0
  48. package/dist/flow/flow-logic/flow-logic-constants.d.ts +38 -0
  49. package/dist/flow/flow-logic/flow-logic-constants.js +118 -0
  50. package/dist/flow/flow-logic/flow-logic-constants.js.map +1 -0
  51. package/dist/flow/flow-logic/flow-logic-diagnostics.d.ts +19 -0
  52. package/dist/flow/flow-logic/flow-logic-diagnostics.js +503 -0
  53. package/dist/flow/flow-logic/flow-logic-diagnostics.js.map +1 -0
  54. package/dist/flow/flow-logic/flow-logic-plugin-helpers.d.ts +62 -0
  55. package/dist/flow/flow-logic/flow-logic-plugin-helpers.js +2092 -0
  56. package/dist/flow/flow-logic/flow-logic-plugin-helpers.js.map +1 -0
  57. package/dist/flow/flow-logic/flow-logic-plugin.d.ts +52 -0
  58. package/dist/flow/flow-logic/flow-logic-plugin.js +283 -0
  59. package/dist/flow/flow-logic/flow-logic-plugin.js.map +1 -0
  60. package/dist/flow/flow-logic/flow-logic-shapes.d.ts +104 -0
  61. package/dist/flow/flow-logic/flow-logic-shapes.js +201 -0
  62. package/dist/flow/flow-logic/flow-logic-shapes.js.map +1 -0
  63. package/dist/flow/plugins/approval-rules-plugin.d.ts +2 -0
  64. package/dist/flow/plugins/approval-rules-plugin.js +49 -0
  65. package/dist/flow/plugins/approval-rules-plugin.js.map +1 -0
  66. package/dist/flow/plugins/flow-action-definition-plugin.d.ts +2 -0
  67. package/dist/flow/plugins/flow-action-definition-plugin.js +286 -0
  68. package/dist/flow/plugins/flow-action-definition-plugin.js.map +1 -0
  69. package/dist/flow/plugins/flow-data-pill-plugin.d.ts +9 -0
  70. package/dist/flow/plugins/flow-data-pill-plugin.js +212 -0
  71. package/dist/flow/plugins/flow-data-pill-plugin.js.map +1 -0
  72. package/dist/flow/plugins/flow-definition-plugin.d.ts +2 -0
  73. package/dist/flow/plugins/flow-definition-plugin.js +1668 -0
  74. package/dist/flow/plugins/flow-definition-plugin.js.map +1 -0
  75. package/dist/flow/plugins/flow-diagnostics-plugin.d.ts +26 -0
  76. package/dist/flow/plugins/flow-diagnostics-plugin.js +217 -0
  77. package/dist/flow/plugins/flow-diagnostics-plugin.js.map +1 -0
  78. package/dist/flow/plugins/flow-instance-plugin.d.ts +12 -0
  79. package/dist/flow/plugins/flow-instance-plugin.js +930 -0
  80. package/dist/flow/plugins/flow-instance-plugin.js.map +1 -0
  81. package/dist/flow/plugins/flow-trigger-instance-plugin.d.ts +2 -0
  82. package/dist/flow/plugins/flow-trigger-instance-plugin.js +324 -0
  83. package/dist/flow/plugins/flow-trigger-instance-plugin.js.map +1 -0
  84. package/dist/flow/plugins/inline-script-plugin.d.ts +39 -0
  85. package/dist/flow/plugins/inline-script-plugin.js +80 -0
  86. package/dist/flow/plugins/inline-script-plugin.js.map +1 -0
  87. package/dist/flow/plugins/step-definition-plugin.d.ts +5 -0
  88. package/dist/flow/plugins/step-definition-plugin.js +71 -0
  89. package/dist/flow/plugins/step-definition-plugin.js.map +1 -0
  90. package/dist/flow/plugins/step-instance-plugin.d.ts +31 -0
  91. package/dist/flow/plugins/step-instance-plugin.js +339 -0
  92. package/dist/flow/plugins/step-instance-plugin.js.map +1 -0
  93. package/dist/flow/plugins/trigger-plugin.d.ts +2 -0
  94. package/dist/flow/plugins/trigger-plugin.js +96 -0
  95. package/dist/flow/plugins/trigger-plugin.js.map +1 -0
  96. package/dist/flow/plugins/wfa-datapill-plugin.d.ts +15 -0
  97. package/dist/flow/plugins/wfa-datapill-plugin.js +178 -0
  98. package/dist/flow/plugins/wfa-datapill-plugin.js.map +1 -0
  99. package/dist/flow/utils/approval-rules-processor.d.ts +13 -0
  100. package/dist/flow/utils/approval-rules-processor.js +267 -0
  101. package/dist/flow/utils/approval-rules-processor.js.map +1 -0
  102. package/dist/flow/utils/built-in-complex-objects.d.ts +19 -0
  103. package/dist/flow/utils/built-in-complex-objects.js +62 -0
  104. package/dist/flow/utils/built-in-complex-objects.js.map +1 -0
  105. package/dist/flow/utils/complex-object-resolver.d.ts +8 -0
  106. package/dist/flow/utils/complex-object-resolver.js +614 -0
  107. package/dist/flow/utils/complex-object-resolver.js.map +1 -0
  108. package/dist/flow/utils/complex-objects.d.ts +36 -0
  109. package/dist/flow/utils/complex-objects.js +481 -0
  110. package/dist/flow/utils/complex-objects.js.map +1 -0
  111. package/dist/flow/utils/data-pill-shapes.d.ts +58 -0
  112. package/dist/flow/utils/data-pill-shapes.js +135 -0
  113. package/dist/flow/utils/data-pill-shapes.js.map +1 -0
  114. package/dist/flow/utils/datapill-transformer.d.ts +110 -0
  115. package/dist/flow/utils/datapill-transformer.js +503 -0
  116. package/dist/flow/utils/datapill-transformer.js.map +1 -0
  117. package/dist/flow/utils/flow-constants.d.ts +65 -0
  118. package/dist/flow/utils/flow-constants.js +223 -0
  119. package/dist/flow/utils/flow-constants.js.map +1 -0
  120. package/dist/flow/utils/flow-io-to-record.d.ts +44 -0
  121. package/dist/flow/utils/flow-io-to-record.js +409 -0
  122. package/dist/flow/utils/flow-io-to-record.js.map +1 -0
  123. package/dist/flow/utils/flow-shapes.d.ts +161 -0
  124. package/dist/flow/utils/flow-shapes.js +255 -0
  125. package/dist/flow/utils/flow-shapes.js.map +1 -0
  126. package/dist/flow/utils/flow-to-xml.d.ts +16 -0
  127. package/dist/flow/utils/flow-to-xml.js +237 -0
  128. package/dist/flow/utils/flow-to-xml.js.map +1 -0
  129. package/dist/flow/utils/flow-variable-processor.d.ts +51 -0
  130. package/dist/flow/utils/flow-variable-processor.js +69 -0
  131. package/dist/flow/utils/flow-variable-processor.js.map +1 -0
  132. package/dist/flow/utils/label-cache-parser.d.ts +7 -0
  133. package/dist/flow/utils/label-cache-parser.js +24 -0
  134. package/dist/flow/utils/label-cache-parser.js.map +1 -0
  135. package/dist/flow/utils/label-cache-processor.d.ts +119 -0
  136. package/dist/flow/utils/label-cache-processor.js +719 -0
  137. package/dist/flow/utils/label-cache-processor.js.map +1 -0
  138. package/dist/flow/utils/pill-string-parser.d.ts +88 -0
  139. package/dist/flow/utils/pill-string-parser.js +306 -0
  140. package/dist/flow/utils/pill-string-parser.js.map +1 -0
  141. package/dist/flow/utils/schema-to-flow-object.d.ts +22 -0
  142. package/dist/flow/utils/schema-to-flow-object.js +318 -0
  143. package/dist/flow/utils/schema-to-flow-object.js.map +1 -0
  144. package/dist/flow/utils/utils.d.ts +117 -0
  145. package/dist/flow/utils/utils.js +345 -0
  146. package/dist/flow/utils/utils.js.map +1 -0
  147. package/dist/import-sets-plugin.d.ts +2 -0
  148. package/dist/import-sets-plugin.js +412 -0
  149. package/dist/import-sets-plugin.js.map +1 -0
  150. package/dist/index.d.ts +24 -1
  151. package/dist/index.js +25 -1
  152. package/dist/index.js.map +1 -1
  153. package/dist/json-plugin.d.ts +4 -4
  154. package/dist/json-plugin.js +21 -7
  155. package/dist/json-plugin.js.map +1 -1
  156. package/dist/list-plugin.js +83 -1
  157. package/dist/list-plugin.js.map +1 -1
  158. package/dist/now-attach-plugin.d.ts +36 -0
  159. package/dist/now-attach-plugin.js +320 -0
  160. package/dist/now-attach-plugin.js.map +1 -0
  161. package/dist/now-config-plugin.js +3 -0
  162. package/dist/now-config-plugin.js.map +1 -1
  163. package/dist/now-include-plugin.js +7 -1
  164. package/dist/now-include-plugin.js.map +1 -1
  165. package/dist/package-json-plugin.js +2 -2
  166. package/dist/package-json-plugin.js.map +1 -1
  167. package/dist/record-plugin.d.ts +35 -0
  168. package/dist/record-plugin.js +109 -23
  169. package/dist/record-plugin.js.map +1 -1
  170. package/dist/repack/index.d.ts +2 -0
  171. package/dist/repack/index.js +8 -0
  172. package/dist/repack/index.js.map +1 -1
  173. package/dist/repack/lint/Rules.js.map +1 -1
  174. package/dist/rest-api-plugin.js +81 -74
  175. package/dist/rest-api-plugin.js.map +1 -1
  176. package/dist/role-plugin.js +1 -0
  177. package/dist/role-plugin.js.map +1 -1
  178. package/dist/server-module-plugin/index.js +53 -6
  179. package/dist/server-module-plugin/index.js.map +1 -1
  180. package/dist/service-catalog/catalog-clientscript-plugin.d.ts +2 -0
  181. package/dist/service-catalog/catalog-clientscript-plugin.js +117 -0
  182. package/dist/service-catalog/catalog-clientscript-plugin.js.map +1 -0
  183. package/dist/service-catalog/catalog-item-plugin.d.ts +2 -0
  184. package/dist/service-catalog/catalog-item-plugin.js +115 -0
  185. package/dist/service-catalog/catalog-item-plugin.js.map +1 -0
  186. package/dist/service-catalog/catalog-ui-policy-plugin.d.ts +2 -0
  187. package/dist/service-catalog/catalog-ui-policy-plugin.js +266 -0
  188. package/dist/service-catalog/catalog-ui-policy-plugin.js.map +1 -0
  189. package/dist/service-catalog/index.d.ts +5 -0
  190. package/dist/service-catalog/index.js +22 -0
  191. package/dist/service-catalog/index.js.map +1 -0
  192. package/dist/service-catalog/record-to-shape.d.ts +6 -0
  193. package/dist/service-catalog/record-to-shape.js +93 -0
  194. package/dist/service-catalog/record-to-shape.js.map +1 -0
  195. package/dist/service-catalog/sc-record-producer-plugin.d.ts +2 -0
  196. package/dist/service-catalog/sc-record-producer-plugin.js +139 -0
  197. package/dist/service-catalog/sc-record-producer-plugin.js.map +1 -0
  198. package/dist/service-catalog/service-catalog-base.d.ts +311 -0
  199. package/dist/service-catalog/service-catalog-base.js +542 -0
  200. package/dist/service-catalog/service-catalog-base.js.map +1 -0
  201. package/dist/service-catalog/service-catalog-diagnostics.d.ts +45 -0
  202. package/dist/service-catalog/service-catalog-diagnostics.js +169 -0
  203. package/dist/service-catalog/service-catalog-diagnostics.js.map +1 -0
  204. package/dist/service-catalog/shape-to-record.d.ts +7 -0
  205. package/dist/service-catalog/shape-to-record.js +232 -0
  206. package/dist/service-catalog/shape-to-record.js.map +1 -0
  207. package/dist/service-catalog/utils.d.ts +313 -0
  208. package/dist/service-catalog/utils.js +1144 -0
  209. package/dist/service-catalog/utils.js.map +1 -0
  210. package/dist/service-catalog/variable-helper.d.ts +43 -0
  211. package/dist/service-catalog/variable-helper.js +92 -0
  212. package/dist/service-catalog/variable-helper.js.map +1 -0
  213. package/dist/service-catalog/variable-set-plugin.d.ts +2 -0
  214. package/dist/service-catalog/variable-set-plugin.js +175 -0
  215. package/dist/service-catalog/variable-set-plugin.js.map +1 -0
  216. package/dist/service-catalog/variables-transform.d.ts +139 -0
  217. package/dist/service-catalog/variables-transform.js +403 -0
  218. package/dist/service-catalog/variables-transform.js.map +1 -0
  219. package/dist/service-portal/widget-plugin.js +4 -1
  220. package/dist/service-portal/widget-plugin.js.map +1 -1
  221. package/dist/sla/sla-validators.d.ts +61 -0
  222. package/dist/sla/sla-validators.js +224 -0
  223. package/dist/sla/sla-validators.js.map +1 -0
  224. package/dist/sla-plugin.d.ts +5 -0
  225. package/dist/sla-plugin.js +280 -0
  226. package/dist/sla-plugin.js.map +1 -0
  227. package/dist/static-content-plugin.d.ts +1 -0
  228. package/dist/static-content-plugin.js +4 -3
  229. package/dist/static-content-plugin.js.map +1 -1
  230. package/dist/table-plugin.js +49 -4
  231. package/dist/table-plugin.js.map +1 -1
  232. package/dist/ui-page-plugin.js +2 -1
  233. package/dist/ui-page-plugin.js.map +1 -1
  234. package/dist/ui-policy-plugin.d.ts +2 -0
  235. package/dist/ui-policy-plugin.js +405 -0
  236. package/dist/ui-policy-plugin.js.map +1 -0
  237. package/dist/utils.d.ts +19 -1
  238. package/dist/utils.js +40 -0
  239. package/dist/utils.js.map +1 -1
  240. package/dist/ux-list-menu-config-plugin.d.ts +2 -0
  241. package/dist/ux-list-menu-config-plugin.js +292 -0
  242. package/dist/ux-list-menu-config-plugin.js.map +1 -0
  243. package/dist/view-plugin.js +1 -1
  244. package/dist/view-plugin.js.map +1 -1
  245. package/dist/workspace-plugin/chrome-tab.d.ts +2 -0
  246. package/dist/workspace-plugin/chrome-tab.js +46 -0
  247. package/dist/workspace-plugin/chrome-tab.js.map +1 -0
  248. package/dist/workspace-plugin/constants.d.ts +52 -0
  249. package/dist/workspace-plugin/constants.js +56 -0
  250. package/dist/workspace-plugin/constants.js.map +1 -0
  251. package/dist/workspace-plugin/fluent-utils.d.ts +9 -0
  252. package/dist/workspace-plugin/fluent-utils.js +60 -0
  253. package/dist/workspace-plugin/fluent-utils.js.map +1 -0
  254. package/dist/workspace-plugin/page.d.ts +8 -0
  255. package/dist/workspace-plugin/page.js +108 -0
  256. package/dist/workspace-plugin/page.js.map +1 -0
  257. package/dist/workspace-plugin/screen.d.ts +1 -0
  258. package/dist/workspace-plugin/screen.js +38 -0
  259. package/dist/workspace-plugin/screen.js.map +1 -0
  260. package/dist/workspace-plugin/templates/index.d.ts +10 -0
  261. package/dist/workspace-plugin/templates/index.js +20 -0
  262. package/dist/workspace-plugin/templates/index.js.map +1 -0
  263. package/dist/workspace-plugin/templates/record-page-composition.d.ts +1 -0
  264. package/dist/workspace-plugin/templates/record-page-composition.js +4043 -0
  265. package/dist/workspace-plugin/templates/record-page-composition.js.map +1 -0
  266. package/dist/workspace-plugin/templates/record-page-data.d.ts +1 -0
  267. package/dist/workspace-plugin/templates/record-page-data.js +527 -0
  268. package/dist/workspace-plugin/templates/record-page-data.js.map +1 -0
  269. package/dist/workspace-plugin/templates/record-page-interalEventMappings.d.ts +1 -0
  270. package/dist/workspace-plugin/templates/record-page-interalEventMappings.js +39 -0
  271. package/dist/workspace-plugin/templates/record-page-interalEventMappings.js.map +1 -0
  272. package/dist/workspace-plugin/templates/record-page-layoutModel.d.ts +1 -0
  273. package/dist/workspace-plugin/templates/record-page-layoutModel.js +55 -0
  274. package/dist/workspace-plugin/templates/record-page-layoutModel.js.map +1 -0
  275. package/dist/workspace-plugin/templates/record-page-properties.d.ts +1 -0
  276. package/dist/workspace-plugin/templates/record-page-properties.js +135 -0
  277. package/dist/workspace-plugin/templates/record-page-properties.js.map +1 -0
  278. package/dist/workspace-plugin/templates/record-page.d.ts +3 -0
  279. package/dist/workspace-plugin/templates/record-page.js +8 -0
  280. package/dist/workspace-plugin/templates/record-page.js.map +1 -0
  281. package/dist/workspace-plugin.d.ts +2 -0
  282. package/dist/workspace-plugin.js +453 -0
  283. package/dist/workspace-plugin.js.map +1 -0
  284. package/package.json +10 -12
  285. package/src/_types/eslint-plugin-es-x.d.ts +17 -0
  286. package/src/_types/md5.js.d.ts +8 -0
  287. package/src/acl-plugin.ts +33 -10
  288. package/src/applicability-plugin.ts +82 -0
  289. package/src/application-menu-plugin.ts +1 -0
  290. package/src/atf/step-configs.ts +14 -12
  291. package/src/atf/test-plugin.ts +46 -24
  292. package/src/basic-syntax-plugin.ts +71 -14
  293. package/src/business-rule-plugin.ts +9 -5
  294. package/src/call-expression-plugin.ts +2 -130
  295. package/src/claims-plugin.ts +1 -1
  296. package/src/client-script-plugin.ts +8 -22
  297. package/src/column/column-helper.ts +65 -3
  298. package/src/column/column-to-record.ts +6 -4
  299. package/src/column-plugin.ts +142 -40
  300. package/src/dashboard/dashboard-component-property-defaults.ts +277 -0
  301. package/src/dashboard/dashboard-component-resolver.ts +69 -0
  302. package/src/dashboard/dashboard-plugin.ts +450 -0
  303. package/src/data-plugin.ts +194 -0
  304. package/src/email-notification-plugin.ts +850 -0
  305. package/src/flow/constants/flow-plugin-constants.ts +79 -0
  306. package/src/flow/flow-logic/flow-logic-constants.ts +120 -0
  307. package/src/flow/flow-logic/flow-logic-diagnostics.ts +591 -0
  308. package/src/flow/flow-logic/flow-logic-plugin-helpers.ts +2550 -0
  309. package/src/flow/flow-logic/flow-logic-plugin.ts +337 -0
  310. package/src/flow/flow-logic/flow-logic-shapes.ts +215 -0
  311. package/src/flow/plugins/approval-rules-plugin.ts +48 -0
  312. package/src/flow/plugins/flow-action-definition-plugin.ts +295 -0
  313. package/src/flow/plugins/flow-data-pill-plugin.ts +258 -0
  314. package/src/flow/plugins/flow-definition-plugin.ts +2173 -0
  315. package/src/flow/plugins/flow-diagnostics-plugin.ts +280 -0
  316. package/src/flow/plugins/flow-instance-plugin.ts +1148 -0
  317. package/src/flow/plugins/flow-trigger-instance-plugin.ts +426 -0
  318. package/src/flow/plugins/inline-script-plugin.ts +83 -0
  319. package/src/flow/plugins/step-definition-plugin.ts +67 -0
  320. package/src/flow/plugins/step-instance-plugin.ts +431 -0
  321. package/src/flow/plugins/trigger-plugin.ts +95 -0
  322. package/src/flow/plugins/wfa-datapill-plugin.ts +213 -0
  323. package/src/flow/utils/approval-rules-processor.ts +298 -0
  324. package/src/flow/utils/built-in-complex-objects.ts +81 -0
  325. package/src/flow/utils/complex-object-resolver.ts +875 -0
  326. package/src/flow/utils/complex-objects.ts +656 -0
  327. package/src/flow/utils/data-pill-shapes.ts +165 -0
  328. package/src/flow/utils/datapill-transformer.ts +632 -0
  329. package/src/flow/utils/flow-constants.ts +276 -0
  330. package/src/flow/utils/flow-io-to-record.ts +533 -0
  331. package/src/flow/utils/flow-shapes.ts +296 -0
  332. package/src/flow/utils/flow-to-xml.ts +318 -0
  333. package/src/flow/utils/flow-variable-processor.ts +100 -0
  334. package/src/flow/utils/label-cache-parser.ts +37 -0
  335. package/src/flow/utils/label-cache-processor.ts +870 -0
  336. package/src/flow/utils/pill-string-parser.ts +375 -0
  337. package/src/flow/utils/schema-to-flow-object.ts +385 -0
  338. package/src/flow/utils/utils.ts +395 -0
  339. package/src/import-sets-plugin.ts +542 -0
  340. package/src/index.ts +25 -1
  341. package/src/json-plugin.ts +31 -12
  342. package/src/list-plugin.ts +91 -1
  343. package/src/now-attach-plugin.ts +403 -0
  344. package/src/now-config-plugin.ts +6 -2
  345. package/src/now-include-plugin.ts +8 -1
  346. package/src/package-json-plugin.ts +3 -3
  347. package/src/record-plugin.ts +126 -30
  348. package/src/repack/index.ts +14 -0
  349. package/src/repack/lint/Rules.ts +1 -10
  350. package/src/rest-api-plugin.ts +106 -100
  351. package/src/role-plugin.ts +1 -0
  352. package/src/server-module-plugin/index.ts +74 -22
  353. package/src/service-catalog/catalog-clientscript-plugin.ts +140 -0
  354. package/src/service-catalog/catalog-item-plugin.ts +162 -0
  355. package/src/service-catalog/catalog-ui-policy-plugin.ts +324 -0
  356. package/src/service-catalog/index.ts +5 -0
  357. package/src/service-catalog/record-to-shape.ts +109 -0
  358. package/src/service-catalog/sc-record-producer-plugin.ts +201 -0
  359. package/src/service-catalog/service-catalog-base.ts +600 -0
  360. package/src/service-catalog/service-catalog-diagnostics.ts +251 -0
  361. package/src/service-catalog/shape-to-record.ts +275 -0
  362. package/src/service-catalog/utils.ts +1362 -0
  363. package/src/service-catalog/variable-helper.ts +135 -0
  364. package/src/service-catalog/variable-set-plugin.ts +197 -0
  365. package/src/service-catalog/variables-transform.ts +438 -0
  366. package/src/service-portal/widget-plugin.ts +4 -1
  367. package/src/sla/sla-validators.ts +331 -0
  368. package/src/sla-plugin.ts +358 -0
  369. package/src/static-content-plugin.ts +2 -2
  370. package/src/table-plugin.ts +66 -9
  371. package/src/ui-page-plugin.ts +2 -1
  372. package/src/ui-policy-plugin.ts +505 -0
  373. package/src/utils.ts +50 -1
  374. package/src/ux-list-menu-config-plugin.ts +312 -0
  375. package/src/view-plugin.ts +1 -1
  376. package/src/workspace-plugin/chrome-tab.ts +44 -0
  377. package/src/workspace-plugin/constants.ts +53 -0
  378. package/src/workspace-plugin/fluent-utils.ts +60 -0
  379. package/src/workspace-plugin/page.ts +139 -0
  380. package/src/workspace-plugin/screen.ts +34 -0
  381. package/src/workspace-plugin/templates/index.ts +17 -0
  382. package/src/workspace-plugin/templates/record-page-composition.ts +4051 -0
  383. package/src/workspace-plugin/templates/record-page-data.ts +523 -0
  384. package/src/workspace-plugin/templates/record-page-interalEventMappings.ts +35 -0
  385. package/src/workspace-plugin/templates/record-page-layoutModel.ts +51 -0
  386. package/src/workspace-plugin/templates/record-page-properties.ts +131 -0
  387. package/src/workspace-plugin/templates/record-page.ts +6 -0
  388. package/src/workspace-plugin.ts +574 -0
@@ -0,0 +1,450 @@
1
+ import { CallExpressionShape, type ObjectShape, Plugin, type Record as RecordType } from '@servicenow/sdk-build-core'
2
+ import { NowIdShape } from '../now-id-plugin'
3
+ import { resolveComponentToSysId, resolveComponentToName } from './dashboard-component-resolver'
4
+ import { DEFAULT_PROPERTY_VALUES, removeRestrictedValues } from './dashboard-component-property-defaults'
5
+
6
+ const transformWidget = (widget: RecordType) =>
7
+ widget.transform(({ $ }) => ({
8
+ $id: $.val(NowIdShape.from(widget)),
9
+ component: $.map((v) => resolveComponentToName(v.toString().getValue())),
10
+ componentProps: $.from('component_props')
11
+ .map((v) => {
12
+ const json = v.ifString()?.getValue()
13
+ const props = json ? JSON.parse(json) : v.getValue()
14
+ return removeRestrictedValues(props)
15
+ })
16
+ .def(DEFAULT_PROPERTY_VALUES),
17
+ height: $.from('h').toNumber(),
18
+ width: $.from('w').toNumber(),
19
+ position: $.map(() => ({
20
+ x: widget.get('x').toNumber().getValue(),
21
+ y: widget.get('y').toNumber().getValue(),
22
+ })),
23
+ }))
24
+
25
+ const createWidgetProperties = (widgetData: ObjectShape, canvas: ObjectShape) =>
26
+ widgetData.transform(({ $ }) => ({
27
+ canvas: $.val(canvas),
28
+ component: $.map((v) => resolveComponentToSysId(v.toString().getValue())),
29
+ component_props: $.from('componentProps').map((v) => {
30
+ const props = v.getValue() || {}
31
+
32
+ return JSON.stringify({ ...DEFAULT_PROPERTY_VALUES, ...props })
33
+ }),
34
+ h: $.from('height').toNumber(),
35
+ w: $.from('width').toNumber(),
36
+ x: $.from('position').map((v) => {
37
+ const posObj = v.asObject()
38
+ return posObj.get('x').toNumber().getValue()
39
+ }),
40
+ y: $.from('position').map((v) => {
41
+ const posObj = v.asObject()
42
+ return posObj.get('y').toNumber().getValue()
43
+ }),
44
+ }))
45
+
46
+ /**
47
+ * Creates a Dashboard (`par_dashboard`).
48
+ *
49
+ * @param config - an object containing the following properties:
50
+ * * **$id** - unique id for the record, typically using `Now.ID["value"]`
51
+ * * **name** - The name of the dashboard
52
+ * * **tabs**? - Array of dashboard tabs (each with $id, name, and widgets array)
53
+ * * **visibilities**? - Array of visibility rules (each with $id and experience reference)
54
+ * * **permissions**? - Array of user permissions (each with $id, user, can_read, can_write, can_share, owner)
55
+ */
56
+ export const DashboardPlugin = Plugin.create({
57
+ name: 'DashboardPlugin',
58
+ records: {
59
+ par_dashboard: {
60
+ relationships: {
61
+ par_dashboard_tab: {
62
+ via: 'dashboard',
63
+ descendant: true,
64
+ relationships: {
65
+ par_dashboard_canvas: {
66
+ via: 'dashboard_tab',
67
+ descendant: true,
68
+ relationships: {
69
+ par_dashboard_widget: {
70
+ via: 'canvas',
71
+ descendant: true,
72
+ },
73
+ },
74
+ },
75
+ },
76
+ },
77
+ par_dashboard_canvas: {
78
+ via: 'dashboard',
79
+ descendant: true,
80
+ relationships: {
81
+ par_dashboard_widget: {
82
+ via: 'canvas',
83
+ descendant: true,
84
+ },
85
+ },
86
+ },
87
+ par_dashboard_visibility: {
88
+ via: 'dashboard',
89
+ descendant: true,
90
+ },
91
+ par_dashboard_permission: {
92
+ via: 'dashboard',
93
+ descendant: true,
94
+ relationships: {
95
+ sys_user: {
96
+ via: 'user',
97
+ inverse: true,
98
+ },
99
+ sys_user_group: {
100
+ via: 'group',
101
+ inverse: true,
102
+ },
103
+ sys_user_role: {
104
+ via: 'role',
105
+ inverse: true,
106
+ },
107
+ },
108
+ },
109
+ },
110
+ toShape(record, { descendants }) {
111
+ const topCanvas = descendants.query('par_dashboard_canvas').find((c) => {
112
+ const tabField = c.get('dashboard_tab')
113
+ return (
114
+ !tabField ||
115
+ tabField.getValue() === undefined ||
116
+ tabField.getValue() === null ||
117
+ tabField.getValue() === ''
118
+ )
119
+ })
120
+
121
+ const topWidgets = topCanvas
122
+ ? descendants
123
+ .query('par_dashboard_widget')
124
+ .filter((w) => {
125
+ const canvasField = w.get('canvas')
126
+ const canvasValue = canvasField.isRecord()
127
+ ? canvasField.asRecord().getId().getValue()
128
+ : canvasField.asRecordId().getValue()
129
+ return canvasValue === topCanvas.getId().getValue()
130
+ })
131
+ .map(transformWidget)
132
+ : []
133
+
134
+ const topLayout = topWidgets.length > 0 ? { widgets: topWidgets } : undefined
135
+
136
+ const tabs = descendants
137
+ .query('par_dashboard_tab')
138
+ .sort((a, b) => a.get('order').toNumber().getValue() - b.get('order').toNumber().getValue())
139
+ .map((tab) => {
140
+ // Find the canvas for this tab
141
+ const canvas = descendants.query('par_dashboard_canvas').find((c) => {
142
+ const tabField = c.get('dashboard_tab')
143
+ if (
144
+ !tabField ||
145
+ tabField.getValue() === undefined ||
146
+ tabField.getValue() === null ||
147
+ tabField.getValue() === ''
148
+ ) {
149
+ return false
150
+ }
151
+ const tabValue = tabField.isRecord()
152
+ ? tabField.asRecord().getId().getValue()
153
+ : tabField.asRecordId().getValue()
154
+ return tabValue === tab.getId().getValue()
155
+ })
156
+
157
+ const widgets = canvas
158
+ ? descendants
159
+ .query('par_dashboard_widget')
160
+ .filter((w) => {
161
+ const canvasField = w.get('canvas')
162
+ const canvasValue = canvasField.isRecord()
163
+ ? canvasField.asRecord().getId().getValue()
164
+ : canvasField.asRecordId().getValue()
165
+ return canvasValue === canvas.getId().getValue()
166
+ })
167
+ .map(transformWidget)
168
+ : []
169
+
170
+ return tab.transform(({ $ }) => ({
171
+ $id: $.val(NowIdShape.from(tab)),
172
+ name: $,
173
+ active: $.toBoolean().def(true),
174
+ widgets: $.val(widgets),
175
+ }))
176
+ })
177
+
178
+ const visibilities = descendants.query('par_dashboard_visibility').map((visibility) => {
179
+ return visibility.transform(({ $ }) => ({
180
+ $id: $.val(NowIdShape.from(visibility)),
181
+ experience: $.from('experience').def(''),
182
+ }))
183
+ })
184
+
185
+ const permissions = descendants.query('par_dashboard_permission').map((permission) =>
186
+ permission.transform(({ $ }) => {
187
+ const hasUser = permission.get('user').asString().getValue() || false
188
+ const hasRole = permission.get('role').asString().getValue() || false
189
+ const hasGroup = permission.get('group').asString().getValue() || false
190
+
191
+ const permissionSubject = hasUser
192
+ ? { user: $ }
193
+ : hasRole
194
+ ? { role: $ }
195
+ : hasGroup
196
+ ? { group: $ }
197
+ : {}
198
+
199
+ return {
200
+ $id: $.val(NowIdShape.from(permission)),
201
+ canRead: $.from('can_read').toBoolean(),
202
+ canShare: $.from('can_share').toBoolean(),
203
+ canWrite: $.from('can_write').toBoolean(),
204
+ owner: $.toBoolean(),
205
+ ...permissionSubject,
206
+ }
207
+ })
208
+ )
209
+
210
+ const dashboardShape = record.transform(({ $ }) => ({
211
+ $id: $.val(NowIdShape.from(record)),
212
+ name: $,
213
+ active: $.toBoolean().def(true),
214
+ tabs: $.val(tabs).def([]),
215
+ visibilities: $.val(visibilities).def([]),
216
+ permissions: $.val(permissions).def([]),
217
+ topLayout: $.val(topLayout),
218
+ }))
219
+
220
+ return {
221
+ success: true,
222
+ value: new CallExpressionShape({
223
+ source: record,
224
+ callee: 'Dashboard',
225
+ args: [dashboardShape],
226
+ }),
227
+ }
228
+ },
229
+ },
230
+ par_dashboard_tab: {
231
+ relationships: {
232
+ par_dashboard_canvas: {
233
+ via: 'dashboard_tab',
234
+ descendant: true,
235
+ },
236
+ },
237
+ },
238
+ par_dashboard_canvas: {
239
+ coalesce: ['dashboard', 'dashboard_tab'],
240
+ relationships: {
241
+ par_dashboard_widget: {
242
+ via: 'canvas',
243
+ descendant: true,
244
+ },
245
+ },
246
+ },
247
+ par_dashboard_visibility: {
248
+ coalesce: ['dashboard', 'experience'],
249
+ },
250
+ par_dashboard_widget: {},
251
+ par_dashboard_user_metadata: {},
252
+
253
+ par_dashboard_permission: {
254
+ coalesce: ['dashboard', 'user', 'group', 'role'],
255
+ },
256
+ },
257
+ shapes: [
258
+ {
259
+ shape: CallExpressionShape,
260
+ fileTypes: ['fluent'],
261
+ async toRecord(source, { factory }) {
262
+ if (source.getCallee() !== 'Dashboard') {
263
+ return { success: false }
264
+ }
265
+
266
+ const arg = source.getArgument(0).asObject()
267
+
268
+ const dashboard = await factory.createRecord({
269
+ source: source,
270
+ table: 'par_dashboard',
271
+ explicitId: arg.get('$id'),
272
+ properties: arg.transform(({ $ }) => ({
273
+ name: $,
274
+ active: $.def(true),
275
+ })),
276
+ })
277
+
278
+ const topLayoutRecords: RecordType[] = []
279
+
280
+ // Process top layout
281
+ if (arg.get('topLayout').ifObject()) {
282
+ const topLayout = arg.get('topLayout').asObject()
283
+
284
+ const topCanvas = await factory.createRecord({
285
+ source,
286
+ table: 'par_dashboard_canvas',
287
+ properties: {
288
+ dashboard: dashboard,
289
+ },
290
+ })
291
+
292
+ const topWidgets = topLayout.get('widgets').ifArray()?.getElements() ?? []
293
+
294
+ topLayoutRecords.push(topCanvas)
295
+
296
+ for (const widgetObj of topWidgets) {
297
+ const widgetData = widgetObj.asObject()
298
+ const widget = await factory.createRecord({
299
+ source: widgetObj,
300
+ table: 'par_dashboard_widget',
301
+ explicitId: widgetData.get('$id'),
302
+ properties: createWidgetProperties(widgetData, topCanvas),
303
+ })
304
+ topLayoutRecords.push(widget)
305
+ }
306
+ }
307
+
308
+ // Process tabs
309
+ const tabs = arg.get('tabs').ifArray()?.getElements() ?? []
310
+ const tabRecords: RecordType[] = []
311
+
312
+ for (const [index, tabObj] of tabs.entries()) {
313
+ const tabData = tabObj.asObject()
314
+ const tab = await factory.createRecord({
315
+ source: tabObj,
316
+ table: 'par_dashboard_tab',
317
+ explicitId: tabData.get('$id'),
318
+ properties: tabData.transform(({ $ }) => ({
319
+ dashboard: $.val(dashboard),
320
+ name: $,
321
+ order: $.val(index),
322
+ active: $.def(true),
323
+ })),
324
+ })
325
+ tabRecords.push(tab)
326
+
327
+ // Create canvas for this tab
328
+ const canvas = await factory.createRecord({
329
+ source: tabObj,
330
+ table: 'par_dashboard_canvas',
331
+ properties: {
332
+ dashboard: dashboard,
333
+ dashboard_tab: tab,
334
+ },
335
+ })
336
+ tabRecords.push(canvas)
337
+
338
+ // Process widgets for this tab's canvas
339
+ const widgets = tabData.get('widgets').ifArray()?.getElements() ?? []
340
+ for (const widgetObj of widgets) {
341
+ const widgetData = widgetObj.asObject()
342
+ const widget = await factory.createRecord({
343
+ source: widgetObj,
344
+ table: 'par_dashboard_widget',
345
+ explicitId: widgetData.get('$id'),
346
+ properties: createWidgetProperties(widgetData, canvas),
347
+ })
348
+ tabRecords.push(widget)
349
+ }
350
+ }
351
+
352
+ // Process visibilities
353
+ const visibilities = arg.get('visibilities').ifArray()?.getElements() ?? []
354
+ const visibilityRecords: RecordType[] = []
355
+
356
+ if (visibilities.length === 0) {
357
+ // Add default visibility if none provided
358
+ visibilityRecords.push(
359
+ await factory.createRecord({
360
+ source: source,
361
+ table: 'par_dashboard_visibility',
362
+ properties: {
363
+ dashboard: dashboard,
364
+ experience: '08c73d60537101100834ddeeff7b1287',
365
+ },
366
+ })
367
+ )
368
+ } else {
369
+ for (const visibility of visibilities) {
370
+ const visibilityObj = visibility.asObject()
371
+
372
+ visibilityRecords.push(
373
+ await factory.createRecord({
374
+ source: visibility,
375
+ table: 'par_dashboard_visibility',
376
+ explicitId: visibilityObj.get('$id'),
377
+ properties: visibilityObj.transform(({ $ }) => {
378
+ return {
379
+ dashboard: $.val(dashboard),
380
+ experience: $.from('experience'),
381
+ }
382
+ }),
383
+ })
384
+ )
385
+ }
386
+ }
387
+
388
+ // Process permissions
389
+ const permissions = arg.get('permissions').ifArray()?.getElements() ?? []
390
+ const permissionRecords: RecordType[] = []
391
+
392
+ for (const permission of permissions) {
393
+ const permissionObj = permission.asObject()
394
+
395
+ // Build properties object
396
+ const properties: Record<string, unknown> = {
397
+ dashboard: dashboard,
398
+ can_read: permissionObj.get('canRead').ifUndefined()
399
+ ? true
400
+ : permissionObj.get('canRead').getValue(),
401
+ can_write: permissionObj.get('canWrite').ifUndefined()
402
+ ? false
403
+ : permissionObj.get('canWrite').getValue(),
404
+ can_share: permissionObj.get('canShare').ifUndefined()
405
+ ? false
406
+ : permissionObj.get('canShare').getValue(),
407
+ owner: permissionObj.get('owner').ifUndefined() ? false : permissionObj.get('owner').getValue(),
408
+ }
409
+
410
+ // Handle user reference (optional)
411
+ const userValue = permissionObj.get('user')
412
+ if (!userValue.ifUndefined()) {
413
+ properties['user'] = userValue
414
+ }
415
+
416
+ // Handle group reference (optional)
417
+ const groupValue = permissionObj.get('group')
418
+ if (!groupValue.ifUndefined()) {
419
+ properties['group'] = groupValue
420
+ }
421
+
422
+ // Handle role reference (optional)
423
+ const roleValue = permissionObj.get('role')
424
+ if (!roleValue.ifUndefined()) {
425
+ properties['role'] = roleValue
426
+ }
427
+
428
+ permissionRecords.push(
429
+ await factory.createRecord({
430
+ source: permission,
431
+ table: 'par_dashboard_permission',
432
+ explicitId: permissionObj.get('$id'),
433
+ properties: properties,
434
+ })
435
+ )
436
+ }
437
+
438
+ return {
439
+ success: true,
440
+ value: dashboard.with(
441
+ ...topLayoutRecords,
442
+ ...tabRecords,
443
+ ...visibilityRecords,
444
+ ...permissionRecords
445
+ ),
446
+ }
447
+ },
448
+ },
449
+ ],
450
+ })
@@ -0,0 +1,194 @@
1
+ import {
2
+ Plugin,
3
+ type Shape,
4
+ type Result,
5
+ type Diagnostics,
6
+ CallExpressionShape,
7
+ DurationShape,
8
+ TimeShape,
9
+ FieldListShape,
10
+ TemplateValueShape,
11
+ DATA_HELPER_NAMES,
12
+ ts,
13
+ } from '@servicenow/sdk-build-core'
14
+ import { getCallExpressionName } from './utils'
15
+
16
+ /**
17
+ * Check if a ts.Node is a data helper call expression.
18
+ */
19
+ export function isDataHelper(node: ts.Node): boolean {
20
+ if (!ts.Node.isCallExpression(node)) {
21
+ return false
22
+ }
23
+ const callee = getCallExpressionName(node)
24
+ return (Object.values(DATA_HELPER_NAMES) as string[]).includes(callee)
25
+ }
26
+
27
+ /**
28
+ * Shape creators for each data helper.
29
+ * Maps helper function names to their shape creation logic.
30
+ * All data helper shapes extend CallExpressionShape.
31
+ */
32
+ const shapeCreators: Record<
33
+ string,
34
+ (shape: CallExpressionShape, diagnostics: Diagnostics) => Result<CallExpressionShape>
35
+ > = {
36
+ [DATA_HELPER_NAMES.DURATION]: createDurationShape,
37
+ [DATA_HELPER_NAMES.TIME]: createTimeShape,
38
+ [DATA_HELPER_NAMES.FIELD_LIST]: createFieldListShape,
39
+ [DATA_HELPER_NAMES.TEMPLATE_VALUE]: createTemplateValueShape,
40
+ }
41
+
42
+ export const DataPlugin = Plugin.create({
43
+ name: 'DataPlugin',
44
+ shapes: [
45
+ {
46
+ shape: CallExpressionShape,
47
+ fileTypes: ['fluent'],
48
+ toSubclass(shape, { diagnostics }) {
49
+ const callee = shape.getCallee()
50
+ const shapeCreator = shapeCreators[callee]
51
+ // Only handle known data helper callees (Duration, Time, FieldList, TemplateValue)
52
+ if (!shapeCreator) {
53
+ return { success: false }
54
+ }
55
+
56
+ return shapeCreator(shape, diagnostics)
57
+ },
58
+ },
59
+ ],
60
+ })
61
+
62
+ /**
63
+ * Helper to validate that all defined fields are non-negative.
64
+ * Returns errors for negative values
65
+ */
66
+ function validateNonNegative(data: Record<string, Shape>, fields: string[]): string[] {
67
+ const errors: string[] = []
68
+ for (const field of fields) {
69
+ const value = data[field]
70
+ if (!value?.isDefined() || !value.isNumber()) {
71
+ continue // Skip undefined or non-numeric (will be caught by constructor)
72
+ }
73
+ const numericValue = value.asNumber().getValue()
74
+ if (numericValue < 0) {
75
+ errors.push(`${field} must be >= 0, got ${numericValue}`)
76
+ }
77
+ }
78
+ return errors
79
+ }
80
+
81
+ /**
82
+ * Helper to validate that at least one field is defined.
83
+ * Returns true if at least one field has a defined value.
84
+ */
85
+ function hasAtLeastOneField(data: Record<string, Shape>, fields: string[]): boolean {
86
+ return fields.some((field) => data[field]?.isDefined())
87
+ }
88
+
89
+ /**
90
+ * Creates a DurationShape from a CallExpressionShape.
91
+ * Validates that duration values are within acceptable ranges.
92
+ */
93
+ function createDurationShape(shape: CallExpressionShape, diagnostics: Diagnostics): Result<DurationShape> {
94
+ const argShape = shape.getArgument(0)
95
+ const duration = argShape.asObject().properties({ resolve: false })
96
+
97
+ // Validate at least one field is provided
98
+ if (!hasAtLeastOneField(duration, ['days', 'hours', 'minutes', 'seconds'])) {
99
+ diagnostics.error(shape, 'Duration must have at least one field defined (days, hours, minutes, or seconds)')
100
+ return { success: false }
101
+ }
102
+
103
+ const errors = validateNonNegative(duration, ['days', 'hours', 'minutes', 'seconds'])
104
+
105
+ if (errors.length > 0) {
106
+ diagnostics.error(shape, `Invalid duration values: ${errors.join(', ')}`)
107
+ return { success: false }
108
+ }
109
+
110
+ return { success: true, value: new DurationShape({ source: shape, value: argShape.asObject() }) }
111
+ }
112
+
113
+ /**
114
+ * Creates a TimeShape from a CallExpressionShape.
115
+ * Validates that time values are within acceptable ranges.
116
+ */
117
+ function createTimeShape(shape: CallExpressionShape, diagnostics: Diagnostics): Result<TimeShape> {
118
+ const argShape = shape.getArgument(0)
119
+ const timeData = argShape.asObject().properties({ resolve: false })
120
+
121
+ // Validate at least one field is provided
122
+ if (!hasAtLeastOneField(timeData, ['hours', 'minutes', 'seconds'])) {
123
+ diagnostics.error(shape, 'Time must have at least one field defined (hours, minutes, or seconds)')
124
+ return { success: false }
125
+ }
126
+
127
+ const errors = validateNonNegative(timeData, ['hours', 'minutes', 'seconds'])
128
+
129
+ if (errors.length > 0) {
130
+ diagnostics.error(shape, `Invalid time values: ${errors.join(', ')}`)
131
+ return { success: false }
132
+ }
133
+
134
+ // Extract and validate optional timezone from second argument
135
+ const tzArg = shape.getArgument(1)
136
+ if (tzArg.isUndefined()) {
137
+ return { success: true, value: new TimeShape({ source: shape, value: argShape.asObject() }) }
138
+ }
139
+
140
+ if (!tzArg.isString()) {
141
+ diagnostics.error(shape, 'Second argument (timezone) must be a string literal')
142
+ return { success: false }
143
+ }
144
+ const timeZone = tzArg.asString().getValue()
145
+ if (!isValidTimeZone(timeZone)) {
146
+ diagnostics.error(
147
+ shape,
148
+ `Invalid IANA timezone: '${timeZone}'. Use a valid timezone like 'America/New_York', 'Europe/London', or 'UTC'.`
149
+ )
150
+ return { success: false }
151
+ }
152
+
153
+ return { success: true, value: new TimeShape({ source: shape, value: argShape.asObject(), timeZone }) }
154
+ }
155
+
156
+ /**
157
+ * Creates a FieldListShape from a CallExpressionShape.
158
+ */
159
+ function createFieldListShape(shape: CallExpressionShape, _diagnostics: Diagnostics): Result<FieldListShape> {
160
+ const fields = shape.getArgument(0).asArray().getElements()
161
+ return { success: true, value: new FieldListShape({ source: shape, fields }) }
162
+ }
163
+
164
+ /**
165
+ * Creates a TemplateValueShape from a CallExpressionShape.
166
+ */
167
+ function createTemplateValueShape(shape: CallExpressionShape, diagnostics: Diagnostics): Result<TemplateValueShape> {
168
+ const value = shape.getArgument(0).asObject().properties({ resolve: false })
169
+
170
+ // Validate that values don't contain ^^ (double caret)
171
+ for (const [key, val] of Object.entries(value)) {
172
+ if (val.isString() && val.getValue().includes('^^')) {
173
+ diagnostics.error(
174
+ shape,
175
+ `Template field '${key}' contains an invalid character sequence: multiple carets (^^). Use a single caret (^) if needed, it will be escaped automatically.`
176
+ )
177
+ return { success: false }
178
+ }
179
+ }
180
+
181
+ return { success: true, value: new TemplateValueShape({ source: shape, value }) }
182
+ }
183
+
184
+ /**
185
+ * Validates if a timezone string is a valid IANA timezone.
186
+ */
187
+ function isValidTimeZone(timeZone: string): boolean {
188
+ try {
189
+ Intl.DateTimeFormat(undefined, { timeZone })
190
+ return true
191
+ } catch {
192
+ return false
193
+ }
194
+ }