@servicenow/sdk-build-plugins 4.4.1 → 4.6.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 (337) hide show
  1. package/dist/acl-plugin.js +54 -4
  2. package/dist/acl-plugin.js.map +1 -1
  3. package/dist/applicability-plugin.js +2 -0
  4. package/dist/applicability-plugin.js.map +1 -1
  5. package/dist/application-menu-plugin.js +2 -0
  6. package/dist/application-menu-plugin.js.map +1 -1
  7. package/dist/arrow-function-plugin.d.ts +6 -1
  8. package/dist/arrow-function-plugin.js +105 -12
  9. package/dist/arrow-function-plugin.js.map +1 -1
  10. package/dist/atf/test-plugin.js +2 -0
  11. package/dist/atf/test-plugin.js.map +1 -1
  12. package/dist/basic-syntax-plugin.js +20 -0
  13. package/dist/basic-syntax-plugin.js.map +1 -1
  14. package/dist/call-expression-plugin.js +1 -0
  15. package/dist/call-expression-plugin.js.map +1 -1
  16. package/dist/claims-plugin.js +1 -0
  17. package/dist/claims-plugin.js.map +1 -1
  18. package/dist/client-script-plugin.js +1 -0
  19. package/dist/client-script-plugin.js.map +1 -1
  20. package/dist/column-plugin.js +4 -7
  21. package/dist/column-plugin.js.map +1 -1
  22. package/dist/cross-scope-privilege-plugin.js +1 -0
  23. package/dist/cross-scope-privilege-plugin.js.map +1 -1
  24. package/dist/dashboard/dashboard-plugin.js +2 -0
  25. package/dist/dashboard/dashboard-plugin.js.map +1 -1
  26. package/dist/data-plugin.js +1 -0
  27. package/dist/data-plugin.js.map +1 -1
  28. package/dist/email-notification-plugin.js +9 -13
  29. package/dist/email-notification-plugin.js.map +1 -1
  30. package/dist/flow/constants/flow-plugin-constants.d.ts +1 -1
  31. package/dist/flow/constants/flow-plugin-constants.js +1 -1
  32. package/dist/flow/constants/flow-plugin-constants.js.map +1 -1
  33. package/dist/flow/flow-logic/flow-logic-diagnostics.js +5 -5
  34. package/dist/flow/flow-logic/flow-logic-diagnostics.js.map +1 -1
  35. package/dist/flow/flow-logic/flow-logic-plugin-helpers.d.ts +82 -2
  36. package/dist/flow/flow-logic/flow-logic-plugin-helpers.js +48 -40
  37. package/dist/flow/flow-logic/flow-logic-plugin-helpers.js.map +1 -1
  38. package/dist/flow/flow-logic/flow-logic-plugin.js +1 -0
  39. package/dist/flow/flow-logic/flow-logic-plugin.js.map +1 -1
  40. package/dist/flow/plugins/approval-rules-plugin.js +1 -0
  41. package/dist/flow/plugins/approval-rules-plugin.js.map +1 -1
  42. package/dist/flow/plugins/flow-action-definition-plugin.js +1232 -55
  43. package/dist/flow/plugins/flow-action-definition-plugin.js.map +1 -1
  44. package/dist/flow/plugins/flow-data-pill-plugin.js +6 -2
  45. package/dist/flow/plugins/flow-data-pill-plugin.js.map +1 -1
  46. package/dist/flow/plugins/flow-definition-plugin.js +23 -44
  47. package/dist/flow/plugins/flow-definition-plugin.js.map +1 -1
  48. package/dist/flow/plugins/flow-diagnostics-plugin.d.ts +2 -2
  49. package/dist/flow/plugins/flow-diagnostics-plugin.js +3 -2
  50. package/dist/flow/plugins/flow-diagnostics-plugin.js.map +1 -1
  51. package/dist/flow/plugins/flow-instance-plugin.js +136 -34
  52. package/dist/flow/plugins/flow-instance-plugin.js.map +1 -1
  53. package/dist/flow/plugins/flow-trigger-instance-plugin.js +1 -0
  54. package/dist/flow/plugins/flow-trigger-instance-plugin.js.map +1 -1
  55. package/dist/flow/plugins/inline-script-plugin.js +1 -0
  56. package/dist/flow/plugins/inline-script-plugin.js.map +1 -1
  57. package/dist/flow/plugins/step-definition-plugin.js +4 -2
  58. package/dist/flow/plugins/step-definition-plugin.js.map +1 -1
  59. package/dist/flow/plugins/step-instance-plugin.d.ts +9 -1
  60. package/dist/flow/plugins/step-instance-plugin.js +649 -135
  61. package/dist/flow/plugins/step-instance-plugin.js.map +1 -1
  62. package/dist/flow/plugins/trigger-plugin.js +2 -0
  63. package/dist/flow/plugins/trigger-plugin.js.map +1 -1
  64. package/dist/flow/plugins/wfa-datapill-plugin.js +21 -5
  65. package/dist/flow/plugins/wfa-datapill-plugin.js.map +1 -1
  66. package/dist/flow/post-install.d.ts +2 -0
  67. package/dist/flow/post-install.js +59 -0
  68. package/dist/flow/post-install.js.map +1 -0
  69. package/dist/flow/utils/complex-object-resolver.js +4 -1
  70. package/dist/flow/utils/complex-object-resolver.js.map +1 -1
  71. package/dist/flow/utils/complex-objects.js +5 -3
  72. package/dist/flow/utils/complex-objects.js.map +1 -1
  73. package/dist/flow/utils/flow-constants.d.ts +90 -2
  74. package/dist/flow/utils/flow-constants.js +430 -7
  75. package/dist/flow/utils/flow-constants.js.map +1 -1
  76. package/dist/flow/utils/flow-io-to-record.d.ts +1 -1
  77. package/dist/flow/utils/flow-io-to-record.js +37 -16
  78. package/dist/flow/utils/flow-io-to-record.js.map +1 -1
  79. package/dist/flow/utils/flow-shapes.js +4 -0
  80. package/dist/flow/utils/flow-shapes.js.map +1 -1
  81. package/dist/flow/utils/flow-to-xml.d.ts +3 -2
  82. package/dist/flow/utils/flow-to-xml.js +3 -4
  83. package/dist/flow/utils/flow-to-xml.js.map +1 -1
  84. package/dist/flow/utils/label-cache-parser.d.ts +9 -2
  85. package/dist/flow/utils/label-cache-parser.js +32 -4
  86. package/dist/flow/utils/label-cache-parser.js.map +1 -1
  87. package/dist/flow/utils/label-cache-processor.d.ts +5 -0
  88. package/dist/flow/utils/label-cache-processor.js +14 -2
  89. package/dist/flow/utils/label-cache-processor.js.map +1 -1
  90. package/dist/flow/utils/pill-shape-helpers.d.ts +15 -0
  91. package/dist/flow/utils/pill-shape-helpers.js +35 -0
  92. package/dist/flow/utils/pill-shape-helpers.js.map +1 -0
  93. package/dist/flow/utils/pill-string-parser.js +1 -0
  94. package/dist/flow/utils/pill-string-parser.js.map +1 -1
  95. package/dist/flow/utils/schema-to-flow-object.d.ts +6 -1
  96. package/dist/flow/utils/schema-to-flow-object.js +131 -15
  97. package/dist/flow/utils/schema-to-flow-object.js.map +1 -1
  98. package/dist/flow/utils/service-catalog.js +5 -1
  99. package/dist/flow/utils/service-catalog.js.map +1 -1
  100. package/dist/flow/utils/utils.d.ts +1 -0
  101. package/dist/flow/utils/utils.js +6 -1
  102. package/dist/flow/utils/utils.js.map +1 -1
  103. package/dist/form-plugin.d.ts +2 -0
  104. package/dist/form-plugin.js +1132 -0
  105. package/dist/form-plugin.js.map +1 -0
  106. package/dist/html-import-plugin.js +1 -0
  107. package/dist/html-import-plugin.js.map +1 -1
  108. package/dist/import-sets-plugin.js +2 -0
  109. package/dist/import-sets-plugin.js.map +1 -1
  110. package/dist/inbound-email-action-plugin.d.ts +10 -0
  111. package/dist/inbound-email-action-plugin.js +128 -0
  112. package/dist/inbound-email-action-plugin.js.map +1 -0
  113. package/dist/index.d.ts +13 -0
  114. package/dist/index.js +17 -1
  115. package/dist/index.js.map +1 -1
  116. package/dist/instance-scan-plugin.d.ts +2 -0
  117. package/dist/instance-scan-plugin.js +293 -0
  118. package/dist/instance-scan-plugin.js.map +1 -0
  119. package/dist/json-plugin.js +1 -0
  120. package/dist/json-plugin.js.map +1 -1
  121. package/dist/list-plugin.js +1 -0
  122. package/dist/list-plugin.js.map +1 -1
  123. package/dist/now-attach-plugin.js +1 -0
  124. package/dist/now-attach-plugin.js.map +1 -1
  125. package/dist/now-config-plugin.js +659 -51
  126. package/dist/now-config-plugin.js.map +1 -1
  127. package/dist/now-id-plugin.js +1 -0
  128. package/dist/now-id-plugin.js.map +1 -1
  129. package/dist/now-include-plugin.js +1 -0
  130. package/dist/now-include-plugin.js.map +1 -1
  131. package/dist/now-ref-plugin.js +1 -0
  132. package/dist/now-ref-plugin.js.map +1 -1
  133. package/dist/now-unresolved-plugin.js +1 -0
  134. package/dist/now-unresolved-plugin.js.map +1 -1
  135. package/dist/package-json-plugin.js +1 -0
  136. package/dist/package-json-plugin.js.map +1 -1
  137. package/dist/property-plugin.js +3 -1
  138. package/dist/property-plugin.js.map +1 -1
  139. package/dist/record-plugin.d.ts +37 -0
  140. package/dist/record-plugin.js +47 -3
  141. package/dist/record-plugin.js.map +1 -1
  142. package/dist/repack/lint/Rules.d.ts +11 -2
  143. package/dist/repack/lint/Rules.js +160 -16
  144. package/dist/repack/lint/Rules.js.map +1 -1
  145. package/dist/repack/lint/index.d.ts +10 -5
  146. package/dist/repack/lint/index.js +76 -50
  147. package/dist/repack/lint/index.js.map +1 -1
  148. package/dist/rest-api-plugin.js +22 -1
  149. package/dist/rest-api-plugin.js.map +1 -1
  150. package/dist/role-plugin.js +1 -0
  151. package/dist/role-plugin.js.map +1 -1
  152. package/dist/schedule-script/index.d.ts +1 -0
  153. package/dist/schedule-script/index.js +18 -0
  154. package/dist/schedule-script/index.js.map +1 -0
  155. package/dist/schedule-script/scheduled-script-plugin.d.ts +2 -0
  156. package/dist/schedule-script/scheduled-script-plugin.js +556 -0
  157. package/dist/schedule-script/scheduled-script-plugin.js.map +1 -0
  158. package/dist/schedule-script/timeZoneConverter.d.ts +61 -0
  159. package/dist/schedule-script/timeZoneConverter.js +170 -0
  160. package/dist/schedule-script/timeZoneConverter.js.map +1 -0
  161. package/dist/script-action-plugin.js +2 -0
  162. package/dist/script-action-plugin.js.map +1 -1
  163. package/dist/script-include-plugin.js +2 -0
  164. package/dist/script-include-plugin.js.map +1 -1
  165. package/dist/server-module-plugin/index.js +13 -2
  166. package/dist/server-module-plugin/index.js.map +1 -1
  167. package/dist/service-catalog/catalog-clientscript-plugin.js +2 -0
  168. package/dist/service-catalog/catalog-clientscript-plugin.js.map +1 -1
  169. package/dist/service-catalog/catalog-item-plugin.js +2 -0
  170. package/dist/service-catalog/catalog-item-plugin.js.map +1 -1
  171. package/dist/service-catalog/catalog-ui-policy-plugin.js +2 -0
  172. package/dist/service-catalog/catalog-ui-policy-plugin.js.map +1 -1
  173. package/dist/service-catalog/sc-record-producer-plugin.js +2 -0
  174. package/dist/service-catalog/sc-record-producer-plugin.js.map +1 -1
  175. package/dist/service-catalog/service-catalog-base.d.ts +18 -18
  176. package/dist/service-catalog/service-catalog-base.js +22 -22
  177. package/dist/service-catalog/service-catalog-base.js.map +1 -1
  178. package/dist/service-catalog/service-catalog-diagnostics.d.ts +6 -0
  179. package/dist/service-catalog/service-catalog-diagnostics.js +20 -0
  180. package/dist/service-catalog/service-catalog-diagnostics.js.map +1 -1
  181. package/dist/service-catalog/shape-to-record.js +7 -2
  182. package/dist/service-catalog/shape-to-record.js.map +1 -1
  183. package/dist/service-catalog/variable-set-plugin.js +2 -0
  184. package/dist/service-catalog/variable-set-plugin.js.map +1 -1
  185. package/dist/service-portal/angular-provider-plugin.js +2 -0
  186. package/dist/service-portal/angular-provider-plugin.js.map +1 -1
  187. package/dist/service-portal/dependency-plugin.js +5 -31
  188. package/dist/service-portal/dependency-plugin.js.map +1 -1
  189. package/dist/service-portal/header-footer-plugin.d.ts +2 -0
  190. package/dist/service-portal/header-footer-plugin.js +50 -0
  191. package/dist/service-portal/header-footer-plugin.js.map +1 -0
  192. package/dist/service-portal/menu-plugin.d.ts +2 -0
  193. package/dist/service-portal/menu-plugin.js +334 -0
  194. package/dist/service-portal/menu-plugin.js.map +1 -0
  195. package/dist/service-portal/page-plugin.d.ts +2 -0
  196. package/dist/service-portal/page-plugin.js +681 -0
  197. package/dist/service-portal/page-plugin.js.map +1 -0
  198. package/dist/service-portal/page-route-map-plugin.d.ts +2 -0
  199. package/dist/service-portal/page-route-map-plugin.js +114 -0
  200. package/dist/service-portal/page-route-map-plugin.js.map +1 -0
  201. package/dist/service-portal/portal-plugin.d.ts +2 -0
  202. package/dist/service-portal/portal-plugin.js +309 -0
  203. package/dist/service-portal/portal-plugin.js.map +1 -0
  204. package/dist/service-portal/theme-plugin.d.ts +2 -0
  205. package/dist/service-portal/theme-plugin.js +112 -0
  206. package/dist/service-portal/theme-plugin.js.map +1 -0
  207. package/dist/service-portal/utils.d.ts +46 -0
  208. package/dist/service-portal/utils.js +331 -0
  209. package/dist/service-portal/utils.js.map +1 -0
  210. package/dist/service-portal/widget-plugin.js +10 -182
  211. package/dist/service-portal/widget-plugin.js.map +1 -1
  212. package/dist/sla-plugin.js +2 -0
  213. package/dist/sla-plugin.js.map +1 -1
  214. package/dist/static-content-plugin.js +5 -0
  215. package/dist/static-content-plugin.js.map +1 -1
  216. package/dist/table-plugin.js +191 -26
  217. package/dist/table-plugin.js.map +1 -1
  218. package/dist/ui-action-plugin.js +3 -4
  219. package/dist/ui-action-plugin.js.map +1 -1
  220. package/dist/ui-page-plugin.js +101 -21
  221. package/dist/ui-page-plugin.js.map +1 -1
  222. package/dist/ui-policy-plugin.js +1 -0
  223. package/dist/ui-policy-plugin.js.map +1 -1
  224. package/dist/user-preference-plugin.js +2 -0
  225. package/dist/user-preference-plugin.js.map +1 -1
  226. package/dist/utils.d.ts +20 -2
  227. package/dist/utils.js +34 -3
  228. package/dist/utils.js.map +1 -1
  229. package/dist/ux-list-menu-config-plugin.js +2 -0
  230. package/dist/ux-list-menu-config-plugin.js.map +1 -1
  231. package/dist/view-plugin.js +9 -3
  232. package/dist/view-plugin.js.map +1 -1
  233. package/dist/workspace-plugin.js +41 -36
  234. package/dist/workspace-plugin.js.map +1 -1
  235. package/package.json +11 -11
  236. package/src/_types/eslint-community-eslint-utils.d.ts +15 -0
  237. package/src/acl-plugin.ts +97 -8
  238. package/src/applicability-plugin.ts +2 -0
  239. package/src/application-menu-plugin.ts +2 -0
  240. package/src/arrow-function-plugin.ts +128 -13
  241. package/src/atf/test-plugin.ts +2 -0
  242. package/src/basic-syntax-plugin.ts +21 -0
  243. package/src/call-expression-plugin.ts +1 -0
  244. package/src/claims-plugin.ts +1 -0
  245. package/src/client-script-plugin.ts +2 -1
  246. package/src/column-plugin.ts +4 -8
  247. package/src/cross-scope-privilege-plugin.ts +2 -1
  248. package/src/dashboard/dashboard-plugin.ts +2 -0
  249. package/src/data-plugin.ts +1 -0
  250. package/src/email-notification-plugin.ts +3 -23
  251. package/src/flow/constants/flow-plugin-constants.ts +1 -1
  252. package/src/flow/flow-logic/flow-logic-diagnostics.ts +5 -6
  253. package/src/flow/flow-logic/flow-logic-plugin-helpers.ts +47 -45
  254. package/src/flow/flow-logic/flow-logic-plugin.ts +1 -0
  255. package/src/flow/plugins/approval-rules-plugin.ts +1 -0
  256. package/src/flow/plugins/flow-action-definition-plugin.ts +1584 -62
  257. package/src/flow/plugins/flow-data-pill-plugin.ts +6 -2
  258. package/src/flow/plugins/flow-definition-plugin.ts +22 -51
  259. package/src/flow/plugins/flow-diagnostics-plugin.ts +3 -2
  260. package/src/flow/plugins/flow-instance-plugin.ts +201 -36
  261. package/src/flow/plugins/flow-trigger-instance-plugin.ts +1 -0
  262. package/src/flow/plugins/inline-script-plugin.ts +1 -0
  263. package/src/flow/plugins/step-definition-plugin.ts +4 -2
  264. package/src/flow/plugins/step-instance-plugin.ts +772 -155
  265. package/src/flow/plugins/trigger-plugin.ts +2 -0
  266. package/src/flow/plugins/wfa-datapill-plugin.ts +26 -5
  267. package/src/flow/post-install.ts +93 -0
  268. package/src/flow/utils/complex-object-resolver.ts +4 -1
  269. package/src/flow/utils/complex-objects.ts +11 -3
  270. package/src/flow/utils/flow-constants.ts +451 -6
  271. package/src/flow/utils/flow-io-to-record.ts +43 -17
  272. package/src/flow/utils/flow-shapes.ts +4 -0
  273. package/src/flow/utils/flow-to-xml.ts +4 -4
  274. package/src/flow/utils/label-cache-parser.ts +33 -4
  275. package/src/flow/utils/label-cache-processor.ts +14 -2
  276. package/src/flow/utils/pill-shape-helpers.ts +42 -0
  277. package/src/flow/utils/pill-string-parser.ts +1 -0
  278. package/src/flow/utils/schema-to-flow-object.ts +183 -15
  279. package/src/flow/utils/service-catalog.ts +5 -2
  280. package/src/flow/utils/utils.ts +12 -1
  281. package/src/form-plugin.ts +1409 -0
  282. package/src/html-import-plugin.ts +1 -0
  283. package/src/import-sets-plugin.ts +2 -0
  284. package/src/inbound-email-action-plugin.ts +145 -0
  285. package/src/index.ts +13 -0
  286. package/src/instance-scan-plugin.ts +313 -0
  287. package/src/json-plugin.ts +1 -0
  288. package/src/list-plugin.ts +2 -1
  289. package/src/now-attach-plugin.ts +1 -0
  290. package/src/now-config-plugin.ts +833 -53
  291. package/src/now-id-plugin.ts +1 -0
  292. package/src/now-include-plugin.ts +1 -0
  293. package/src/now-ref-plugin.ts +1 -0
  294. package/src/now-unresolved-plugin.ts +1 -0
  295. package/src/package-json-plugin.ts +1 -0
  296. package/src/property-plugin.ts +6 -1
  297. package/src/record-plugin.ts +56 -6
  298. package/src/repack/lint/Rules.ts +171 -22
  299. package/src/repack/lint/index.ts +80 -56
  300. package/src/rest-api-plugin.ts +28 -2
  301. package/src/role-plugin.ts +2 -1
  302. package/src/schedule-script/index.ts +1 -0
  303. package/src/schedule-script/scheduled-script-plugin.ts +690 -0
  304. package/src/schedule-script/timeZoneConverter.ts +188 -0
  305. package/src/script-action-plugin.ts +2 -0
  306. package/src/script-include-plugin.ts +2 -0
  307. package/src/server-module-plugin/index.ts +14 -2
  308. package/src/service-catalog/catalog-clientscript-plugin.ts +2 -0
  309. package/src/service-catalog/catalog-item-plugin.ts +2 -0
  310. package/src/service-catalog/catalog-ui-policy-plugin.ts +2 -0
  311. package/src/service-catalog/sc-record-producer-plugin.ts +2 -0
  312. package/src/service-catalog/service-catalog-base.ts +22 -22
  313. package/src/service-catalog/service-catalog-diagnostics.ts +30 -0
  314. package/src/service-catalog/shape-to-record.ts +8 -2
  315. package/src/service-catalog/variable-set-plugin.ts +2 -0
  316. package/src/service-portal/angular-provider-plugin.ts +2 -0
  317. package/src/service-portal/dependency-plugin.ts +6 -53
  318. package/src/service-portal/header-footer-plugin.ts +57 -0
  319. package/src/service-portal/menu-plugin.ts +413 -0
  320. package/src/service-portal/page-plugin.ts +805 -0
  321. package/src/service-portal/page-route-map-plugin.ts +124 -0
  322. package/src/service-portal/portal-plugin.ts +342 -0
  323. package/src/service-portal/theme-plugin.ts +135 -0
  324. package/src/service-portal/utils.ts +470 -0
  325. package/src/service-portal/widget-plugin.ts +18 -224
  326. package/src/sla-plugin.ts +2 -0
  327. package/src/static-content-plugin.ts +4 -0
  328. package/src/table-plugin.ts +228 -37
  329. package/src/ui-action-plugin.ts +3 -8
  330. package/src/ui-page-plugin.ts +110 -21
  331. package/src/ui-policy-plugin.ts +2 -1
  332. package/src/user-preference-plugin.ts +2 -0
  333. package/src/utils.ts +42 -2
  334. package/src/ux-list-menu-config-plugin.ts +2 -0
  335. package/src/view-plugin.ts +11 -4
  336. package/src/workspace-plugin.ts +45 -43
  337. package/src/_types/eslint-plugin-es-x.d.ts +0 -17
@@ -1,16 +1,43 @@
1
1
  import {
2
2
  Plugin,
3
3
  CallExpressionShape,
4
+ DurationShape,
5
+ IdentifierShape,
4
6
  ObjectShape,
7
+ PropertyAccessShape,
8
+ TemplateExpressionShape,
9
+ TemplateValueShape,
5
10
  type Record as BuildRecord,
6
11
  type Factory,
7
12
  type Shape,
8
13
  type Source,
14
+ type Diagnostics,
9
15
  } from '@servicenow/sdk-build-core'
10
- import type { NowIdShape } from '../../now-id-plugin'
11
- import { sysIdToUuid } from '../utils/utils'
16
+ import { NowIdShape } from '../../now-id-plugin'
17
+ import { getBuiltInStepIdentifier, sysIdToUuid } from '../utils/utils'
12
18
  import { COLUMN_API_TO_TYPE } from '../../column/column-helper'
13
- import { ACTION_STEP_INSTANCE_API_NAME } from '../utils/flow-constants'
19
+ import {
20
+ ACTION_STEP_INSTANCE_API_NAME,
21
+ BUILT_IN_STEP_DEFINITIONS,
22
+ BUILT_IN_STEP_NAME_TO_SYSID,
23
+ BUILT_IN_STEP_PREFIX,
24
+ buildExtVarAttributes,
25
+ getVarEntryName,
26
+ getVarEntryType,
27
+ FLOW_OBJECT_API_NAME,
28
+ FLOW_ARRAY_API_NAME,
29
+ } from '../utils/flow-constants'
30
+ import { normalizeInputValue } from './flow-instance-plugin'
31
+ import { ApprovalRulesShape, ApprovalDueDateShape } from '../utils/flow-shapes'
32
+ import { createSdkDocEntry } from '../../utils'
33
+ import {
34
+ generateSchemaFromObject,
35
+ getComplexObjectAttributes,
36
+ formatComplexObjectAttributes,
37
+ } from '../utils/complex-objects'
38
+
39
+ import { PillShape } from '../utils/data-pill-shapes'
40
+ import { findAncestorByCalleeName } from '../utils/utils'
14
41
 
15
42
  // Error handling type mapping: string to number
16
43
  const ERROR_HANDLING_TYPE_MAP: Record<string, number> = {
@@ -18,6 +45,148 @@ const ERROR_HANDLING_TYPE_MAP: Record<string, number> = {
18
45
  dont_stop_the_action: 2,
19
46
  }
20
47
 
48
+ /**
49
+ * Resolves a TemplateValue field shape to a datapill string (e.g., "{{action.desc|string}}").
50
+ * Handles two cases:
51
+ * 1. Already resolved PillShape — call getValue() directly
52
+ * 2. Unresolved wfa.dataPill() CallExpressionShape — extract pill info from arguments
53
+ * @param cidMap - Optional map of step variable name → CID for direct lookup (avoids AST walking)
54
+ * Returns undefined if the field is not a datapill.
55
+ */
56
+ function resolveFieldToPillString(fieldShape: Shape, cidMap?: Map<string, string>): string | undefined {
57
+ // Case 1: Already a PillShape (e.g., processed by the datapill plugin)
58
+ if (fieldShape instanceof PillShape) {
59
+ return fieldShape.getValue()
60
+ }
61
+
62
+ // Case 2: Unresolved wfa.dataPill(expression, type) CallExpressionShape
63
+ if (fieldShape instanceof CallExpressionShape) {
64
+ const callee = fieldShape.getCallee()
65
+ if (callee !== 'wfa.dataPill') {
66
+ return undefined
67
+ }
68
+
69
+ const typeArg = fieldShape.getArgument(1)
70
+
71
+ // Extract property path — try Shape API first, then AST node directly
72
+ const propertyNames: string[] = []
73
+ const expressionArg = fieldShape.getArgument(0, false) // 0, false
74
+ if (expressionArg instanceof PropertyAccessShape) {
75
+ expressionArg.getElements().forEach((el: Shape) => {
76
+ if (el instanceof IdentifierShape) {
77
+ propertyNames.push(el.getName())
78
+ }
79
+ })
80
+ }
81
+
82
+ if (propertyNames.length < 2) {
83
+ return undefined
84
+ }
85
+
86
+ let prefix = 'action'
87
+ let pathParts: string[]
88
+
89
+ if (propertyNames[1] === 'inputs') {
90
+ // params.inputs.xxx → action pill
91
+ const originalNode = fieldShape.getOriginalNode?.()
92
+ if (originalNode) {
93
+ const actionAncestor = findAncestorByCalleeName(originalNode, 'Action')
94
+ prefix = actionAncestor ? 'action' : 'subflow'
95
+ }
96
+ pathParts = propertyNames.slice(2)
97
+ } else {
98
+ // Could be a step variable reference: create_record_step.record.short_description
99
+ // Resolve CID via cidMap lookup (O(1))
100
+ const varName = propertyNames[0]
101
+ const stepCid = varName ? cidMap?.get(varName) : undefined
102
+ if (stepCid) {
103
+ prefix = `step[${stepCid}]`
104
+ pathParts = propertyNames.slice(1)
105
+ } else {
106
+ // Cannot resolve step CID — return undefined so the caller can handle the failure
107
+ return undefined
108
+ }
109
+ }
110
+
111
+ const dataType = typeArg?.ifString()?.getValue()
112
+ const typeSuffix = dataType ? `|${dataType}` : ''
113
+
114
+ return `{{${prefix}.${pathParts.join('.')}${typeSuffix}}}`
115
+ }
116
+
117
+ // Case 3: Already a resolved pill string
118
+ const val = fieldShape.getValue()
119
+ if (typeof val === 'string' && val.startsWith('{{') && val.endsWith('}}')) {
120
+ return val
121
+ }
122
+
123
+ return undefined
124
+ }
125
+
126
+ /**
127
+ * Extracts pill type annotations from a pill string and stores them in the pillTypeMap.
128
+ * Captures types from both step pills ({{step[CID].path|type}}) and action pills
129
+ * ({{action.path|type}}). The "|type" portion is captured before it gets stripped
130
+ * for the element_mapping value. The collected types are used later when building the label_cache.
131
+ */
132
+ const STEP_PILL_TYPE_REGEX = /\{\{step\[([^\]]+)\]\.([^|}]+)(?:\|([^}]+))?\}\}/g
133
+ const ACTION_PILL_TYPE_REGEX = /\{\{action\.([^|}]+)(?:\|([^}]+))?\}\}/g
134
+ function collectPillTypes(pillString: string, pillTypeMap?: Map<string, string>): void {
135
+ if (!pillTypeMap) {
136
+ return
137
+ }
138
+ for (const match of pillString.matchAll(STEP_PILL_TYPE_REGEX)) {
139
+ const [, cid, pillPath, dataType] = match
140
+ if (cid && pillPath && dataType) {
141
+ pillTypeMap.set(`${cid}::${pillPath}`, dataType)
142
+ }
143
+ }
144
+ for (const match of pillString.matchAll(ACTION_PILL_TYPE_REGEX)) {
145
+ const [, path, dataType] = match
146
+ if (path && dataType) {
147
+ pillTypeMap.set(`action::${path}`, dataType)
148
+ }
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Strips the |type suffix from a pill string.
154
+ * e.g., "{{action.desc|string}}" → "{{action.desc}}"
155
+ *
156
+ * Note: This is called on individual pill strings (from resolveFieldToPillString),
157
+ * never on concatenated multi-pill strings — so no `g` flag is needed.
158
+ */
159
+ function stripPillType(pill: string): string {
160
+ return pill.replace(/\|[^}]+/, '')
161
+ }
162
+
163
+ /**
164
+ * Resolves a TemplateExpressionShape into a concatenated string, replacing
165
+ * datapill spans with their pill strings (type-stripped) and collecting pill types.
166
+ * Returns the resolved string and whether any pills were found.
167
+ */
168
+ function resolveTemplateExpression(
169
+ templateShape: TemplateExpressionShape,
170
+ cidMap?: Map<string, string>,
171
+ pillTypeMap?: Map<string, string>
172
+ ): { result: string; hasPills: boolean } {
173
+ let result = templateShape.getLiteralText()
174
+ let hasPills = false
175
+ for (const span of templateShape.getSpans()) {
176
+ const expr = span.getExpression()
177
+ const pillStr = resolveFieldToPillString(expr as Shape, cidMap)
178
+ if (pillStr) {
179
+ collectPillTypes(pillStr, pillTypeMap)
180
+ result += stripPillType(pillStr)
181
+ hasPills = true
182
+ } else {
183
+ result += String(expr.getValue?.() ?? '')
184
+ }
185
+ result += span.getLiteralText()
186
+ }
187
+ return { result, hasPills }
188
+ }
189
+
21
190
  /**
22
191
  * StepInstanceShape represents a step instance within a custom action's body
23
192
  * This class handles the shape transformation for step instances
@@ -29,6 +198,10 @@ export class StepInstanceShape extends CallExpressionShape {
29
198
  private stepLabel: string
30
199
  private inputs: ObjectShape | undefined
31
200
  private inputDefinitions: ObjectShape | undefined
201
+ /** Map of step variable name → CID, set by ActionDefinitionPlugin for step pill resolution in Action() bodies */
202
+ private _cidMap?: Map<string, string>
203
+ /** Map of "CID::pillPath" → dataType, populated during toRecord for label_cache type propagation */
204
+ private _pillTypeMap?: Map<string, string>
32
205
 
33
206
  constructor(args: {
34
207
  source: Source
@@ -41,7 +214,7 @@ export class StepInstanceShape extends CallExpressionShape {
41
214
  inputDefinitions?: ObjectShape
42
215
  }) {
43
216
  const { source, sysId, config, stepDefinitionSysId, stepLabel, inputs, inputDefinitions } = args
44
- super({ source, callee: 'StepInstance', args: [sysId, config, stepDefinitionSysId] })
217
+ super({ source, callee: 'wfa.actionStep', args: [sysId, config, stepDefinitionSysId] })
45
218
  this.config = config
46
219
  this.sysId = sysId
47
220
  this.stepDefinitionSysId = stepDefinitionSysId
@@ -73,10 +246,27 @@ export class StepInstanceShape extends CallExpressionShape {
73
246
  getInputDefinitions(): ObjectShape | undefined {
74
247
  return this.inputDefinitions
75
248
  }
249
+
250
+ setCidMap(cidMap: Map<string, string>): void {
251
+ this._cidMap = cidMap
252
+ }
253
+
254
+ getCidMap(): Map<string, string> | undefined {
255
+ return this._cidMap
256
+ }
257
+
258
+ setPillTypeMap(pillTypeMap: Map<string, string>): void {
259
+ this._pillTypeMap = pillTypeMap
260
+ }
261
+
262
+ getPillTypeMap(): Map<string, string> | undefined {
263
+ return this._pillTypeMap
264
+ }
76
265
  }
77
266
 
78
267
  export const StepInstancePlugin = Plugin.create({
79
268
  name: 'StepInstancePlugin',
269
+ docs: [createSdkDocEntry('wfa.actionStep', ['sys_hub_step_instance'])],
80
270
  shapes: [
81
271
  {
82
272
  shape: CallExpressionShape,
@@ -98,12 +288,8 @@ export const StepInstancePlugin = Plugin.create({
98
288
 
99
289
  const [stepDefinition, stepInstanceConfig, inputs] = args
100
290
 
101
- // Validate first argument is a StepDefinition
102
- if (
103
- !(stepDefinition instanceof CallExpressionShape) ||
104
- stepDefinition.getCallee() !== 'ActionStepDefinition'
105
- ) {
106
- diagnostics.error(callExpression, 'Expected first argument to be a ActionStepDefinition')
291
+ if (!stepDefinition) {
292
+ diagnostics.error(callExpression, 'Missing step definition argument')
107
293
  return { success: false }
108
294
  }
109
295
 
@@ -119,7 +305,51 @@ export const StepInstancePlugin = Plugin.create({
119
305
  return { success: false }
120
306
  }
121
307
 
122
- const stepConfig = stepDefinition.getArgument(0).asObject()
308
+ let stepDefinitionSysId: string
309
+ let stepLabel: string
310
+ let inputDefinitions: ObjectShape | undefined
311
+
312
+ // First argument can be a string (built-in step name), IdentifierShape (actionStep.xxx),
313
+ // or ActionStepDefinition() call
314
+ const stepNameValue = stepDefinition.ifString()?.getValue()
315
+ if (stepNameValue) {
316
+ // Built-in step referenced by name string
317
+ stepDefinitionSysId = BUILT_IN_STEP_NAME_TO_SYSID[stepNameValue] ?? ''
318
+ stepLabel = stepNameValue
319
+ if (!stepDefinitionSysId) {
320
+ diagnostics.error(callExpression, `Unknown built-in step type '${stepNameValue}'`)
321
+ return { success: false }
322
+ }
323
+ } else if (stepDefinition instanceof IdentifierShape) {
324
+ // Built-in step referenced via actionStep.xxx identifier
325
+ const identifierName = stepDefinition.getName()
326
+ const prefix = `${BUILT_IN_STEP_PREFIX}.`
327
+ const resolvedName = identifierName.startsWith(prefix)
328
+ ? identifierName.slice(prefix.length)
329
+ : identifierName
330
+ stepDefinitionSysId = BUILT_IN_STEP_NAME_TO_SYSID[resolvedName] ?? ''
331
+ stepLabel = resolvedName
332
+ if (!stepDefinitionSysId) {
333
+ diagnostics.error(callExpression, `Unknown built-in step type '${identifierName}'`)
334
+ return { success: false }
335
+ }
336
+ } else if (
337
+ stepDefinition instanceof CallExpressionShape &&
338
+ stepDefinition.getCallee() === 'ActionStepDefinition'
339
+ ) {
340
+ // Custom step definition
341
+ const stepConfig = stepDefinition.getArgument(0).asObject()
342
+ stepDefinitionSysId = stepConfig.get('$id')?.getValue() as string
343
+ stepLabel = stepConfig.get('name')?.getValue() as string
344
+ inputDefinitions = stepConfig.get('inputs')?.ifObject()?.asObject()
345
+ } else {
346
+ diagnostics.error(
347
+ callExpression,
348
+ 'Expected first argument to be a step type name string, actionStep.xxx identifier, or ActionStepDefinition'
349
+ )
350
+ return { success: false }
351
+ }
352
+
123
353
  const shapeArgs: {
124
354
  source: Source
125
355
  config: ObjectShape
@@ -132,10 +362,10 @@ export const StepInstancePlugin = Plugin.create({
132
362
  source: callExpression,
133
363
  sysId: stepInstanceConfig.get('$id')?.getValue() as NowIdShape | Shape,
134
364
  config: stepInstanceConfig,
135
- stepDefinitionSysId: stepConfig.get('$id')?.getValue() as string,
136
- stepLabel: stepConfig.get('name')?.getValue() as string,
137
- inputDefinitions: stepConfig.get('inputs')?.asObject(),
365
+ stepDefinitionSysId,
366
+ stepLabel,
138
367
  inputs: inputs,
368
+ ...(inputDefinitions ? { inputDefinitions } : {}),
139
369
  }
140
370
 
141
371
  return {
@@ -147,10 +377,11 @@ export const StepInstancePlugin = Plugin.create({
147
377
  {
148
378
  shape: StepInstanceShape,
149
379
  fileTypes: ['fluent'],
150
- async toRecord(callExpression, { factory }) {
380
+ async toRecord(callExpression, { factory, diagnostics }) {
151
381
  const stepInstanceRecord = await buildStepInstanceRecord({
152
382
  callExpression,
153
383
  factory,
384
+ diagnostics,
154
385
  values: callExpression.getInputs() as ObjectShape,
155
386
  sysId: callExpression.getSysId(),
156
387
  stepDefinitionSysId: callExpression.getStepDefinitionSysId(),
@@ -168,6 +399,12 @@ export const StepInstancePlugin = Plugin.create({
168
399
  sys_hub_step_ext_output: {
169
400
  coalesce: ['model', 'element'],
170
401
  },
402
+ sys_complex_object: {
403
+ coalesce: ['name'],
404
+ },
405
+ sys_element_mapping: {
406
+ coalesce: ['field', 'id'],
407
+ },
171
408
  sys_hub_step_instance: {
172
409
  relationships: {
173
410
  sys_variable_value: {
@@ -191,87 +428,137 @@ export const StepInstancePlugin = Plugin.create({
191
428
  descendant: true,
192
429
  },
193
430
  },
194
- // toShape(record, { descendants, diagnostics }) {
195
- // // Get the step definition reference
196
- // const stepDefinitionRecords = descendants.query('sys_flow_step_definition')
197
- // if (stepDefinitionRecords.length === 0) {
198
- // diagnostics.error(record, 'Could not find step definition for step instance')
199
- // return { success: false }
200
- // }
201
-
202
- // const stepDefinition = stepDefinitionRecords[0]
203
- // if (!stepDefinition) {
204
- // diagnostics.error(record, 'Step definition is undefined')
205
- // return { success: false }
206
- // }
207
-
208
- // // Build the config object from sys_variable_value records
209
- // const variableValues = descendants.query('sys_variable_value')
210
- // const configObj: globalThis.Record<string, any> = {}
211
-
212
- // for (const varValue of variableValues) {
213
- // const variableSysId = varValue.get('variable')?.asString()?.getValue()
214
- // const value = varValue.get('value')?.asString()?.getValue()
215
-
216
- // // Find the matching input definition to get the element name
217
- // const inputRecords = descendants.query('sys_flow_step_definition_input', { sysId: variableSysId })
218
- // if (inputRecords.length > 0) {
219
- // const elementName = inputRecords[0]?.get('element')?.asString()?.getValue()
220
- // if (elementName) {
221
- // // Try to parse JSON values, otherwise use as string
222
- // try {
223
- // configObj[elementName] = JSON.parse(value || '')
224
- // } catch {
225
- // configObj[elementName] = value
226
- // }
227
- // }
228
- // }
229
- // }
230
-
231
- // // Add error_handling_type and label from the step instance record itself
232
- // const errorHandlingType = record.get('error_handling_type')?.asNumber()?.getValue()
233
- // if (errorHandlingType !== undefined && errorHandlingType !== 1) {
234
- // configObj['error_handling_type'] = errorHandlingType
235
- // }
236
-
237
- // const label = record.get('label')?.asString()?.getValue()
238
- // const stepName = stepDefinition.get('name')?.asString()?.getValue()
239
- // if (label && label !== stepName) {
240
- // configObj['label'] = label
241
- // }
242
-
243
- // // Create the StepDefinition CallExpressionShape reference
244
- // const stepDefinitionShape = new CallExpressionShape({
245
- // source: stepDefinition,
246
- // callee: 'StepDefinition',
247
- // args: [
248
- // stepDefinition.transform(({ $ }) => ({
249
- // $id: $.val(NowIdShape.from(stepDefinition)),
250
- // name: $,
251
- // })),
252
- // ],
253
- // })
254
-
255
- // // Create the config ObjectShape
256
- // const configProperties: globalThis.Record<string, any> = {}
257
- // for (const [key, value] of Object.entries(configObj)) {
258
- // configProperties[key] = value
259
- // }
260
-
261
- // const configShape = new ObjectShape({
262
- // source: record,
263
- // properties: configProperties,
264
- // })
265
-
266
- // return {
267
- // success: true,
268
- // value: new CallExpressionShape({
269
- // source: record,
270
- // callee: 'StepInstance',
271
- // args: [stepDefinitionShape, NowIdShape.from(record), configShape],
272
- // }),
273
- // }
274
- // },
431
+ toShape(record, { descendants, logger }) {
432
+ // Skip step instances that belong to an action definition
433
+ // those are handled by ActionDefinitionPlugin's toShape for Action() definitions
434
+ const actionRef = record.get('action')?.asString()?.getValue()
435
+ if (actionRef) {
436
+ return { success: false }
437
+ }
438
+
439
+ const stepDefinitionRecords = descendants.query('sys_flow_step_definition')
440
+ const variableValues = descendants.query('sys_variable_value')
441
+ const configObj: globalThis.Record<string, unknown> = {}
442
+
443
+ let stepDefinitionShape: CallExpressionShape | IdentifierShape | string
444
+ let stepName: string | undefined
445
+
446
+ if (stepDefinitionRecords.length > 0) {
447
+ // Custom step definition found in descendants
448
+ const stepDefinition = stepDefinitionRecords[0]
449
+ if (!stepDefinition) {
450
+ logger.warn('Step definition is undefined')
451
+ return { success: false }
452
+ }
453
+
454
+ stepName = stepDefinition.get('name')?.asString()?.getValue()
455
+
456
+ // Resolve variable values using input definition records from descendants
457
+ for (const varValue of variableValues) {
458
+ const variableSysId = varValue.get('variable')?.asString()?.getValue()
459
+ const value = varValue.get('value')?.asString()?.getValue()
460
+
461
+ const inputRecords = descendants.query('sys_flow_step_definition_input', {
462
+ sysId: variableSysId,
463
+ })
464
+ if (inputRecords.length > 0) {
465
+ const elementName = inputRecords[0]?.get('element')?.asString()?.getValue()
466
+ if (elementName) {
467
+ try {
468
+ configObj[elementName] = JSON.parse(value || '')
469
+ } catch {
470
+ configObj[elementName] = value
471
+ }
472
+ }
473
+ }
474
+ }
475
+
476
+ stepDefinitionShape = new CallExpressionShape({
477
+ source: stepDefinition,
478
+ callee: 'ActionStepDefinition',
479
+ args: [
480
+ stepDefinition.transform(({ $ }) => ({
481
+ $id: $.val(NowIdShape.from(stepDefinition)),
482
+ name: $,
483
+ })),
484
+ ],
485
+ })
486
+ } else {
487
+ // OOB/built-in step definition — not in XML export
488
+ const stepTypeSysId = record.get('step_type')?.asString()?.getValue()
489
+ if (!stepTypeSysId) {
490
+ logger.warn(`Step instance ${record.getId().getValue()} has no step_type reference`)
491
+ return { success: false }
492
+ }
493
+
494
+ const builtInDef = BUILT_IN_STEP_DEFINITIONS[stepTypeSysId]
495
+ if (!builtInDef) {
496
+ logger.warn(
497
+ `Unknown OOB step definition ${stepTypeSysId} for step instance ${record.getId().getValue()}`
498
+ )
499
+ return { success: false }
500
+ }
501
+
502
+ stepName = builtInDef.name
503
+
504
+ // Resolve variable values using the built-in definition's input/output mappings
505
+ for (const varValue of variableValues) {
506
+ const variableSysId = varValue.get('variable')?.asString()?.getValue()
507
+ const value = varValue.get('value')?.asString()?.getValue()
508
+ if (variableSysId) {
509
+ const entry = builtInDef.inputs[variableSysId] ?? builtInDef.outputs[variableSysId]
510
+ const elementName = entry ? getVarEntryName(entry) : undefined
511
+ const uiType = entry ? getVarEntryType(entry) : undefined
512
+ if (elementName && value != null) {
513
+ configObj[elementName] = uiType ? normalizeInputValue(value, uiType, record) : value
514
+ }
515
+ }
516
+ }
517
+
518
+ // Built-in/OOB step: emit actionStep.xxx reference
519
+ const stepIdentifier = getBuiltInStepIdentifier(stepTypeSysId)
520
+ stepDefinitionShape = stepIdentifier
521
+ ? new IdentifierShape({ source: record, name: stepIdentifier })
522
+ : builtInDef.name
523
+ }
524
+
525
+ // Build step instance config (2nd arg): $id, label, error_handling_type
526
+ const configProperties: globalThis.Record<string, unknown> = {
527
+ $id: NowIdShape.from(record),
528
+ }
529
+
530
+ const errorHandlingRaw = record.get('error_handling_type')
531
+ const errorHandlingType =
532
+ errorHandlingRaw?.ifNumber()?.getValue() ?? Number(errorHandlingRaw?.ifString()?.getValue())
533
+ if (errorHandlingType && errorHandlingType !== 1 && !Number.isNaN(errorHandlingType)) {
534
+ configProperties['error_handling_type'] = errorHandlingType
535
+ }
536
+
537
+ const label = record.get('label')?.asString()?.getValue()
538
+ if (label && label !== stepName) {
539
+ configProperties['label'] = label
540
+ }
541
+
542
+ const stepInstanceConfig = new ObjectShape({
543
+ source: record,
544
+ properties: configProperties,
545
+ })
546
+
547
+ // Build inputs (3rd arg): resolved variable values only
548
+ const inputsShape = new ObjectShape({
549
+ source: record,
550
+ properties: { ...configObj },
551
+ })
552
+
553
+ return {
554
+ success: true,
555
+ value: new CallExpressionShape({
556
+ source: record,
557
+ callee: 'wfa.actionStep',
558
+ args: [stepDefinitionShape, stepInstanceConfig, inputsShape],
559
+ }),
560
+ }
561
+ },
275
562
  },
276
563
  },
277
564
  })
@@ -279,6 +566,7 @@ export const StepInstancePlugin = Plugin.create({
279
566
  async function buildStepInstanceRecord({
280
567
  callExpression,
281
568
  factory,
569
+ diagnostics,
282
570
  values,
283
571
  sysId,
284
572
  stepDefinitionSysId,
@@ -287,12 +575,19 @@ async function buildStepInstanceRecord({
287
575
  }: {
288
576
  callExpression: StepInstanceShape
289
577
  factory: Factory
578
+ diagnostics: Diagnostics
290
579
  values: ObjectShape
291
580
  sysId: NowIdShape | Shape
292
581
  stepDefinitionSysId: string
293
582
  stepLabel: string
294
583
  inputs: ObjectShape | undefined
295
584
  }): Promise<BuildRecord> {
585
+ // resolve: false — keep PillShapes and other ResolvableShapes intact (same reason as createVariableRecords).
586
+ // Using .getValue() on the parent ObjectShape would deeply resolve nested PillShapes into symbols.
587
+ const valuesArray = values.properties({ resolve: false })
588
+ const cidMap = callExpression.getCidMap()
589
+ const pillTypeMap = callExpression.getPillTypeMap()
590
+
296
591
  // Create step instance record
297
592
  const stepInstanceRecord = await factory.createRecord({
298
593
  source: callExpression,
@@ -302,7 +597,8 @@ async function buildStepInstanceRecord({
302
597
  step_type: stepDefinitionSysId,
303
598
  order: 1,
304
599
  active: true,
305
- error_handling_type: ERROR_HANDLING_TYPE_MAP[values.get('errorHandlingType')?.getValue() as string] ?? 1,
600
+ error_handling_type:
601
+ ERROR_HANDLING_TYPE_MAP[valuesArray['errorHandlingType']?.ifString()?.getValue() ?? ''] ?? 1,
306
602
  label: stepLabel,
307
603
  },
308
604
  })
@@ -311,20 +607,31 @@ async function buildStepInstanceRecord({
311
607
  })
312
608
  const stepInstanceSysId = updatedStepInstanceRecord.getId().getValue()
313
609
  // Create sys_variable_value records for each input value
314
- const variableValueRecords = await createVariableRecords(values, inputs, factory, callExpression, stepInstanceSysId)
610
+ const stepDataRecords = await createVariableRecords(
611
+ valuesArray,
612
+ inputs,
613
+ factory,
614
+ callExpression,
615
+ stepInstanceSysId,
616
+ stepDefinitionSysId,
617
+ cidMap
618
+ )
315
619
  const extendedInputRecords: BuildRecord[] = []
316
620
  const extendedOutputRecords: BuildRecord[] = []
317
621
  const extendedVariableValueRecords: BuildRecord[] = []
622
+ const inputVariablesShape = valuesArray['inputVariables']
623
+ if (inputVariablesShape) {
624
+ const inputVarObj = inputVariablesShape.asObject()
625
+ const inputVarProps = inputVarObj.properties({ resolve: false })
626
+
627
+ const extInputTableName = `var__m_sys_hub_step_ext_input_${stepInstanceSysId}`
318
628
 
319
- const valuesArray = values.properties()
320
- // biome-ignore lint/suspicious/noExplicitAny: Dynamic input variable config
321
- const inputVariables = valuesArray['inputVariables']?.getValue() as Record<string, any>
322
- if (inputVariables) {
323
- for (const [name, config] of Object.entries(inputVariables)) {
324
- const label = config.label
325
- const mandatory = config.mandatory
326
- const defaultValue = config.defaultValue ?? ''
327
- const value = config.value
629
+ for (const [name, configShapeRaw] of Object.entries(inputVarProps)) {
630
+ const configObj = configShapeRaw.asObject()
631
+ const configProps = configObj.properties({ resolve: false })
632
+ const label = (configProps['label']?.ifString?.()?.getValue() ?? name) as string
633
+ const defaultValue = (configProps['defaultValue']?.ifString?.()?.getValue() ?? '') as string
634
+ const valueShape = configProps['value']
328
635
  const extInputRecord = await factory.createRecord({
329
636
  source: callExpression,
330
637
  table: 'sys_hub_step_ext_input',
@@ -333,89 +640,397 @@ async function buildStepInstanceRecord({
333
640
  model: stepInstanceSysId,
334
641
  model_id: stepInstanceSysId,
335
642
  model_table: 'sys_hub_step_instance',
336
- name: `var__m_sys_hub_step_ext_input_${stepInstanceSysId}`,
643
+ name: extInputTableName,
337
644
  element: name,
338
645
  label: label,
339
- mandatory: mandatory,
340
646
  default_value: defaultValue,
647
+ attributes: buildExtVarAttributes('string'),
648
+ internal_type: 'string',
341
649
  },
342
650
  })
343
651
  extendedInputRecords.push(extInputRecord)
344
- extendedVariableValueRecords.push(
345
- await factory.createRecord({
346
- source: callExpression,
347
- table: 'sys_variable_value',
348
- properties: {
349
- document: 'sys_hub_step_instance',
350
- document_key: stepInstanceSysId,
351
- order: 100,
352
- value: value,
353
- variable: extInputRecord.getId().getValue(),
354
- },
355
- })
356
- )
652
+
653
+ if (!valueShape) {
654
+ // No value provided — still create a sys_variable_value record with empty value
655
+ // so the platform recognizes the ext input variable exists
656
+ extendedVariableValueRecords.push(
657
+ await factory.createRecord({
658
+ source: callExpression,
659
+ table: 'sys_variable_value',
660
+ properties: {
661
+ document: 'sys_hub_step_instance',
662
+ document_key: stepInstanceSysId,
663
+ order: 100,
664
+ value: '',
665
+ variable: extInputRecord.getId().getValue(),
666
+ },
667
+ })
668
+ )
669
+ } else {
670
+ // Check if value is a datapill — if so, create sys_element_mapping instead of sys_variable_value
671
+ const pillString = resolveFieldToPillString(valueShape as Shape, cidMap)
672
+ if (pillString) {
673
+ collectPillTypes(pillString, pillTypeMap)
674
+ extendedVariableValueRecords.push(
675
+ await factory.createRecord({
676
+ source: callExpression,
677
+ table: 'sys_element_mapping',
678
+ properties: {
679
+ field: name,
680
+ id: stepInstanceSysId,
681
+ table: extInputTableName,
682
+ value: stripPillType(pillString),
683
+ },
684
+ })
685
+ )
686
+ } else if (valueShape.is(TemplateExpressionShape)) {
687
+ const { result, hasPills } = resolveTemplateExpression(
688
+ valueShape as TemplateExpressionShape,
689
+ cidMap,
690
+ pillTypeMap
691
+ )
692
+ if (hasPills) {
693
+ extendedVariableValueRecords.push(
694
+ await factory.createRecord({
695
+ source: callExpression,
696
+ table: 'sys_element_mapping',
697
+ properties: {
698
+ field: name,
699
+ id: stepInstanceSysId,
700
+ table: extInputTableName,
701
+ value: result,
702
+ },
703
+ })
704
+ )
705
+ } else {
706
+ extendedVariableValueRecords.push(
707
+ await factory.createRecord({
708
+ source: callExpression,
709
+ table: 'sys_variable_value',
710
+ properties: {
711
+ document: 'sys_hub_step_instance',
712
+ document_key: stepInstanceSysId,
713
+ order: 100,
714
+ value: result,
715
+ variable: extInputRecord.getId().getValue(),
716
+ },
717
+ })
718
+ )
719
+ }
720
+ } else {
721
+ // Simple value → store in sys_variable_value
722
+ const rawVal = valueShape.ifString()?.getValue() ?? valueShape.getValue?.()
723
+ const resolvedValue = typeof rawVal === 'symbol' ? '' : (rawVal ?? '')
724
+ extendedVariableValueRecords.push(
725
+ await factory.createRecord({
726
+ source: callExpression,
727
+ table: 'sys_variable_value',
728
+ properties: {
729
+ document: 'sys_hub_step_instance',
730
+ document_key: stepInstanceSysId,
731
+ order: 100,
732
+ value: resolvedValue,
733
+ variable: extInputRecord.getId().getValue(),
734
+ },
735
+ })
736
+ )
737
+ }
738
+ }
357
739
  }
358
740
  }
359
741
 
360
742
  const outputVariables = valuesArray['outputVariables']
743
+ const complexObjectRecords: BuildRecord[] = []
361
744
  if (outputVariables) {
362
745
  const outputItemShape = outputVariables.asObject()
363
- const outputProperties = outputItemShape.properties()
746
+ const outputProperties = outputItemShape.properties({ resolve: false })
364
747
 
365
748
  for (const [columnName, columnCallExpr] of Object.entries(outputProperties)) {
366
749
  const callExpr = columnCallExpr.as(CallExpressionShape)
367
- const columnType = callExpr.getCallee() // e.g., 'StringColumn', 'IntegerColumn'
750
+ const columnType = callExpr.getCallee() // e.g., 'StringColumn', 'IntegerColumn', 'FlowObject', 'FlowArray'
368
751
  const columnConfig = callExpr.getArgument(0)?.asObject()
369
752
  const columnLabel = columnConfig?.get('label')?.getValue() as string
370
753
  const mandatory = columnConfig?.get('mandatory')?.getValue() as boolean
371
- const internalType = COLUMN_API_TO_TYPE[columnType] || 'string'
372
- const extOutputRecord = await factory.createRecord({
373
- source: callExpression,
374
- table: 'sys_hub_step_ext_output',
375
- properties: {
376
- active: true,
377
- model: stepInstanceSysId,
378
- model_id: stepInstanceSysId,
379
- model_table: 'sys_hub_step_instance',
380
- name: `var__m_sys_hub_step_ext_output_${stepInstanceSysId}`,
381
- element: columnName,
382
- label: columnLabel || columnName,
383
- internal_type: internalType,
384
- mandatory: mandatory,
385
- },
386
- })
387
- extendedOutputRecords.push(extOutputRecord)
754
+
755
+ // Handle FlowObject and FlowArray complex objects
756
+ if (columnType === FLOW_OBJECT_API_NAME || columnType === FLOW_ARRAY_API_NAME) {
757
+ const coTypeName = columnConfig?.get('co_type_name')?.ifString()?.getValue()
758
+ const varSysId = `${stepInstanceSysId}_${columnName}`
759
+ const complexObjectId = coTypeName || `FD${varSysId}`
760
+ const isArray = columnType === FLOW_ARRAY_API_NAME
761
+
762
+ // Generate schema for complex object
763
+ const schemaObj = generateSchemaFromObject(
764
+ columnConfig,
765
+ complexObjectId,
766
+ columnName,
767
+ stepInstanceSysId,
768
+ 0,
769
+ isArray,
770
+ diagnostics,
771
+ false
772
+ )
773
+
774
+ // Create sys_complex_object record
775
+ const explicitId = columnConfig?.get('$id')?.ifString()?.getValue()
776
+ const complexRecord = await factory.createRecord({
777
+ source: callExpression,
778
+ table: 'sys_complex_object',
779
+ properties: {
780
+ name: complexObjectId,
781
+ namespace: 'FlowDesigner',
782
+ type: isArray ? 'complex_object_collection' : 'complex_object_schema',
783
+ serialized_content: JSON.stringify(schemaObj),
784
+ ...(explicitId ? { sys_id: explicitId } : {}),
785
+ },
786
+ })
787
+ complexObjectRecords.push(complexRecord)
788
+
789
+ // Get complex object attributes
790
+ const systemAttributes = getComplexObjectAttributes(schemaObj, complexObjectId, isArray)
791
+ const attributesStr = formatComplexObjectAttributes(systemAttributes)
792
+
793
+ // Create ext_output record with complex object type
794
+ const extOutputRecord = await factory.createRecord({
795
+ source: callExpression,
796
+ table: 'sys_hub_step_ext_output',
797
+ properties: {
798
+ active: true,
799
+ model: stepInstanceSysId,
800
+ model_id: stepInstanceSysId,
801
+ model_table: 'sys_hub_step_instance',
802
+ name: `var__m_sys_hub_step_ext_output_${stepInstanceSysId}`,
803
+ element: columnName,
804
+ label: columnLabel || columnName,
805
+ internal_type: 'string',
806
+ max_length: 65000,
807
+ mandatory: mandatory,
808
+ attributes: attributesStr,
809
+ },
810
+ })
811
+ extendedOutputRecords.push(extOutputRecord)
812
+ } else {
813
+ // Handle regular column types (StringColumn, IntegerColumn, etc.)
814
+ const internalType = COLUMN_API_TO_TYPE[columnType] || 'string'
815
+ const maxLength = columnConfig?.get('maxLength')?.ifNumber()?.getValue()
816
+ const hint = columnConfig?.get('hint')?.ifString()?.getValue()
817
+ const defaultValue = columnConfig?.get('default')?.ifString()?.getValue()
818
+ const extOutputRecord = await factory.createRecord({
819
+ source: callExpression,
820
+ table: 'sys_hub_step_ext_output',
821
+ properties: {
822
+ active: true,
823
+ model: stepInstanceSysId,
824
+ model_id: stepInstanceSysId,
825
+ model_table: 'sys_hub_step_instance',
826
+ name: `var__m_sys_hub_step_ext_output_${stepInstanceSysId}`,
827
+ element: columnName,
828
+ label: columnLabel || columnName,
829
+ internal_type: internalType,
830
+ mandatory: mandatory,
831
+ ...(maxLength != null ? { max_length: maxLength } : {}),
832
+ ...(hint ? { hint } : {}),
833
+ ...(defaultValue ? { default_value: defaultValue } : {}),
834
+ attributes: buildExtVarAttributes(internalType),
835
+ },
836
+ })
837
+ extendedOutputRecords.push(extOutputRecord)
838
+ }
388
839
  }
389
840
  }
390
841
 
391
842
  return updatedStepInstanceRecord.with(
392
- ...variableValueRecords,
843
+ ...stepDataRecords,
393
844
  ...extendedInputRecords,
394
845
  ...extendedVariableValueRecords,
395
- ...extendedOutputRecords
846
+ ...extendedOutputRecords,
847
+ ...complexObjectRecords
396
848
  )
397
849
  }
398
850
  async function createVariableRecords(
399
- values: ObjectShape,
851
+ valuesProperties: globalThis.Record<string, Shape>,
400
852
  inputs: ObjectShape | undefined,
401
853
  factory: Factory,
402
854
  callExpression: StepInstanceShape,
403
- stepInstanceSysId: string
855
+ stepInstanceSysId: string,
856
+ stepDefinitionSysId: string,
857
+ cidMap?: Map<string, string>
404
858
  ) {
405
- const properties = values.properties()
406
859
  // Filter out inputVariables, outputVariables and errorHandlingType as they are handled separately
407
- const filteredEntries = Object.entries(properties).filter(
860
+ const filteredEntries = Object.entries(valuesProperties).filter(
408
861
  ([key]) => key !== 'inputVariables' && key !== 'outputVariables' && key !== 'errorHandlingType'
409
862
  )
410
- return await Promise.all(
411
- filteredEntries.map(([key, valueShape]) => {
863
+
864
+ // Build reverse lookup (elementName → varSysId) from BUILT_IN_STEP_DEFINITIONS
865
+ const builtInDef = BUILT_IN_STEP_DEFINITIONS[stepDefinitionSysId]
866
+ const elementToVarSysId: globalThis.Record<string, string> = {}
867
+ if (builtInDef) {
868
+ for (const [varSysId, entry] of Object.entries(builtInDef.inputs)) {
869
+ elementToVarSysId[getVarEntryName(entry)] = varSysId
870
+ }
871
+ for (const [varSysId, entry] of Object.entries(builtInDef.outputs)) {
872
+ elementToVarSysId[getVarEntryName(entry)] = varSysId
873
+ }
874
+ }
875
+
876
+ const pillTypeMap = callExpression.getPillTypeMap()
877
+ const allRecords: BuildRecord[] = []
878
+ await Promise.all(
879
+ filteredEntries.map(async ([key, valueShape]) => {
880
+ // Try resolving from inputDefinitions shape first, then fall back to built-in map
881
+ let variableSysId = ''
412
882
  const input = inputs?.get(key)
413
- const variableSysId =
414
- input instanceof CallExpressionShape
415
- ? (input.getArgument(0).asObject().get('sysId')?.getValue() as string)
416
- : ''
417
- const actualValue = valueShape.getValue?.() ?? valueShape.toString()
418
- return factory.createRecord({
883
+ if (input instanceof CallExpressionShape) {
884
+ variableSysId = (input.getArgument(0).asObject().get('sysId')?.getValue() as string) ?? ''
885
+ }
886
+ if (!variableSysId) {
887
+ variableSysId = elementToVarSysId[key] ?? ''
888
+ }
889
+
890
+ // ApprovalDueDateShape: store JSON in sys_element_mapping.value (ServiceNow reads from there)
891
+ // and create sys_variable_value with empty value
892
+ if (valueShape.is(ApprovalDueDateShape)) {
893
+ const jsonValue = (valueShape as ApprovalDueDateShape).toString().getValue()
894
+ const [elementMappingRecord, variableValueRecord] = await Promise.all([
895
+ factory.createRecord({
896
+ source: callExpression,
897
+ table: 'sys_element_mapping',
898
+ properties: {
899
+ field: key,
900
+ id: stepInstanceSysId,
901
+ table: `var__m_sys_flow_step_definition_input_${stepDefinitionSysId}`,
902
+ value: jsonValue,
903
+ },
904
+ }),
905
+ factory.createRecord({
906
+ source: callExpression,
907
+ table: 'sys_variable_value',
908
+ properties: {
909
+ document: 'sys_hub_step_instance',
910
+ document_key: stepInstanceSysId,
911
+ order: 100,
912
+ // value intentionally empty: ServiceNow reads due_date JSON from sys_element_mapping, not here
913
+ value: '',
914
+ variable: variableSysId,
915
+ },
916
+ }),
917
+ ])
918
+ allRecords.push(elementMappingRecord, variableValueRecord)
919
+ return
920
+ }
921
+
922
+ // Handle TemplateValueShape specially - serialize to ServiceNow format.
923
+ // When TemplateValue contains datapills, the platform stores the entire encoded string
924
+ // (with pills inline) in a single sys_element_mapping record with field=<parent input name>.
925
+ let actualValue: unknown
926
+ if (valueShape.is(TemplateValueShape)) {
927
+ const templateObj = (valueShape as TemplateValueShape).getTemplateValue()
928
+ const entries: string[] = []
929
+ let hasPills = false
930
+
931
+ for (const [field, fieldShape] of templateObj.entries({ resolve: false })) {
932
+ const pillString = resolveFieldToPillString(fieldShape, cidMap)
933
+ if (pillString) {
934
+ collectPillTypes(pillString, pillTypeMap)
935
+ entries.push(`${field}=${stripPillType(pillString)}`)
936
+ hasPills = true
937
+ } else if (fieldShape.is(TemplateExpressionShape)) {
938
+ const resolved = resolveTemplateExpression(
939
+ fieldShape as TemplateExpressionShape,
940
+ cidMap,
941
+ pillTypeMap
942
+ )
943
+ if (resolved.hasPills) {
944
+ hasPills = true
945
+ }
946
+ const escapedValue = resolved.result.replace(/\^/g, '^^')
947
+ entries.push(`${field}=${escapedValue}`)
948
+ } else {
949
+ const resolved = fieldShape.getValue()
950
+ const escapedValue = String(resolved).replace(/\^/g, '^^')
951
+ entries.push(`${field}=${escapedValue}`)
952
+ }
953
+ }
954
+
955
+ const encodedValue = entries.join('^')
956
+
957
+ if (hasPills) {
958
+ // TemplateValue with datapills → single sys_element_mapping record
959
+ // No sys_variable_value for this field — platform reads from element_mapping only
960
+ allRecords.push(
961
+ await factory.createRecord({
962
+ source: callExpression,
963
+ table: 'sys_element_mapping',
964
+ properties: {
965
+ field: key,
966
+ id: stepInstanceSysId,
967
+ table: `var__m_sys_flow_step_definition_input_${stepDefinitionSysId}`,
968
+ value: encodedValue,
969
+ },
970
+ })
971
+ )
972
+ return
973
+ }
974
+
975
+ // No datapills — standard encoded string in sys_variable_value
976
+ actualValue = encodedValue ? `${encodedValue}^EQ` : ''
977
+ } else if (valueShape.is(DurationShape)) {
978
+ // DurationShape.getValue() returns a symbol, so use toString() instead
979
+ actualValue = (valueShape as DurationShape).toString().getValue()
980
+ } else if (valueShape.is(ApprovalRulesShape)) {
981
+ // ApprovalRulesShape.getValue() returns a JSON object, not a string.
982
+ // Previously fell through to the generic getValue() path which stored a raw [object Object].
983
+ // toString() correctly serializes it to the JSON string ServiceNow expects.
984
+ actualValue = valueShape.toString().getValue()
985
+ } else if (valueShape.is(TemplateExpressionShape)) {
986
+ const { result, hasPills } = resolveTemplateExpression(
987
+ valueShape as TemplateExpressionShape,
988
+ cidMap,
989
+ pillTypeMap
990
+ )
991
+ if (hasPills) {
992
+ allRecords.push(
993
+ await factory.createRecord({
994
+ source: callExpression,
995
+ table: 'sys_element_mapping',
996
+ properties: {
997
+ field: key,
998
+ id: stepInstanceSysId,
999
+ table: `var__m_sys_flow_step_definition_input_${stepDefinitionSysId}`,
1000
+ value: result,
1001
+ },
1002
+ })
1003
+ )
1004
+ return
1005
+ }
1006
+ actualValue = result
1007
+ } else {
1008
+ // Check if it's a wfa.dataPill() CallExpressionShape (step output reference)
1009
+ // that needs to be resolved to a pill string for sys_element_mapping
1010
+ const pillString = resolveFieldToPillString(valueShape as Shape, cidMap)
1011
+ if (pillString) {
1012
+ collectPillTypes(pillString, pillTypeMap)
1013
+ allRecords.push(
1014
+ await factory.createRecord({
1015
+ source: callExpression,
1016
+ table: 'sys_element_mapping',
1017
+ properties: {
1018
+ field: key,
1019
+ id: stepInstanceSysId,
1020
+ table: `var__m_sys_flow_step_definition_input_${stepDefinitionSysId}`,
1021
+ value: stripPillType(pillString),
1022
+ },
1023
+ })
1024
+ )
1025
+ return
1026
+ }
1027
+ const rawValue = valueShape.getValue?.()
1028
+ // Guard against symbol values (e.g., DurationShape, unresolved shapes with { resolve: false })
1029
+ // since factory.createRecord cannot serialize symbols. Fall back to empty string.
1030
+ actualValue = typeof rawValue === 'symbol' ? '' : (rawValue ?? '')
1031
+ }
1032
+
1033
+ const record = await factory.createRecord({
419
1034
  source: callExpression,
420
1035
  table: 'sys_variable_value',
421
1036
  properties: {
@@ -426,6 +1041,8 @@ async function createVariableRecords(
426
1041
  variable: variableSysId,
427
1042
  },
428
1043
  })
1044
+ allRecords.push(record)
429
1045
  })
430
1046
  )
1047
+ return allRecords
431
1048
  }