@servicenow/sdk-build-plugins 3.0.2 → 4.0.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 (359) hide show
  1. package/dist/acl-plugin.d.ts +19 -0
  2. package/dist/acl-plugin.js +210 -0
  3. package/dist/acl-plugin.js.map +1 -0
  4. package/dist/application-menu-plugin.d.ts +18 -0
  5. package/dist/application-menu-plugin.js +104 -0
  6. package/dist/application-menu-plugin.js.map +1 -0
  7. package/dist/arrow-function-plugin.d.ts +16 -0
  8. package/dist/arrow-function-plugin.js +107 -0
  9. package/dist/arrow-function-plugin.js.map +1 -0
  10. package/dist/atf/step-configs.d.ts +37 -0
  11. package/dist/atf/step-configs.js +2236 -0
  12. package/dist/atf/step-configs.js.map +1 -0
  13. package/dist/atf/test-plugin.d.ts +4 -0
  14. package/dist/atf/test-plugin.js +591 -0
  15. package/dist/atf/test-plugin.js.map +1 -0
  16. package/dist/basic-syntax-plugin.d.ts +2 -0
  17. package/dist/basic-syntax-plugin.js +636 -0
  18. package/dist/basic-syntax-plugin.js.map +1 -0
  19. package/dist/business-rule-plugin.d.ts +3 -0
  20. package/dist/business-rule-plugin.js +205 -0
  21. package/dist/business-rule-plugin.js.map +1 -0
  22. package/dist/call-expression-plugin.d.ts +2 -0
  23. package/dist/call-expression-plugin.js +175 -0
  24. package/dist/call-expression-plugin.js.map +1 -0
  25. package/dist/client-script-plugin.d.ts +29 -0
  26. package/dist/client-script-plugin.js +157 -0
  27. package/dist/client-script-plugin.js.map +1 -0
  28. package/dist/column/column-helper.d.ts +12 -0
  29. package/dist/column/column-helper.js +84 -0
  30. package/dist/column/column-helper.js.map +1 -0
  31. package/dist/column/column-to-record.d.ts +3 -0
  32. package/dist/column/column-to-record.js +105 -0
  33. package/dist/column/column-to-record.js.map +1 -0
  34. package/dist/column-plugin.d.ts +8 -0
  35. package/dist/column-plugin.js +453 -0
  36. package/dist/column-plugin.js.map +1 -0
  37. package/dist/cross-scope-privilege-plugin.d.ts +15 -0
  38. package/dist/cross-scope-privilege-plugin.js +82 -0
  39. package/dist/cross-scope-privilege-plugin.js.map +1 -0
  40. package/dist/html-import-plugin.d.ts +2 -0
  41. package/dist/html-import-plugin.js +72 -0
  42. package/dist/html-import-plugin.js.map +1 -0
  43. package/dist/index.d.ts +37 -21
  44. package/dist/index.js +40 -45
  45. package/dist/index.js.map +1 -1
  46. package/dist/json-plugin.d.ts +15 -0
  47. package/dist/json-plugin.js +104 -0
  48. package/dist/json-plugin.js.map +1 -0
  49. package/dist/list-plugin.d.ts +2 -0
  50. package/dist/list-plugin.js +191 -0
  51. package/dist/list-plugin.js.map +1 -0
  52. package/dist/now-config-plugin.d.ts +4 -0
  53. package/dist/now-config-plugin.js +154 -0
  54. package/dist/now-config-plugin.js.map +1 -0
  55. package/dist/now-id-plugin.d.ts +11 -0
  56. package/dist/now-id-plugin.js +71 -0
  57. package/dist/now-id-plugin.js.map +1 -0
  58. package/dist/now-include-plugin.d.ts +16 -0
  59. package/dist/now-include-plugin.js +118 -0
  60. package/dist/now-include-plugin.js.map +1 -0
  61. package/dist/now-ref-plugin.d.ts +2 -0
  62. package/dist/now-ref-plugin.js +43 -0
  63. package/dist/now-ref-plugin.js.map +1 -0
  64. package/dist/now-unresolved-plugin.d.ts +2 -0
  65. package/dist/now-unresolved-plugin.js +32 -0
  66. package/dist/now-unresolved-plugin.js.map +1 -0
  67. package/dist/package-json-plugin.d.ts +2 -0
  68. package/dist/package-json-plugin.js +70 -0
  69. package/dist/package-json-plugin.js.map +1 -0
  70. package/dist/property-plugin.d.ts +2 -0
  71. package/dist/property-plugin.js +105 -0
  72. package/dist/property-plugin.js.map +1 -0
  73. package/dist/record-plugin.d.ts +43 -0
  74. package/dist/record-plugin.js +147 -0
  75. package/dist/record-plugin.js.map +1 -0
  76. package/dist/repack/index.d.ts +1 -0
  77. package/dist/repack/index.js +10 -2
  78. package/dist/repack/index.js.map +1 -1
  79. package/dist/repack/lint/Rules.d.ts +1 -1
  80. package/dist/repack/lint/Rules.js +7 -3
  81. package/dist/repack/lint/Rules.js.map +1 -1
  82. package/dist/repack/lint/index.js +1 -1
  83. package/dist/rest-api-plugin.d.ts +2 -0
  84. package/dist/rest-api-plugin.js +469 -0
  85. package/dist/rest-api-plugin.js.map +1 -0
  86. package/dist/role-plugin.d.ts +2 -0
  87. package/dist/role-plugin.js +117 -0
  88. package/dist/role-plugin.js.map +1 -0
  89. package/dist/script-action-plugin.d.ts +2 -0
  90. package/dist/script-action-plugin.js +62 -0
  91. package/dist/script-action-plugin.js.map +1 -0
  92. package/dist/script-include-plugin.d.ts +2 -0
  93. package/dist/script-include-plugin.js +102 -0
  94. package/dist/script-include-plugin.js.map +1 -0
  95. package/dist/server-module-plugin/index.d.ts +14 -0
  96. package/dist/server-module-plugin/index.js +378 -0
  97. package/dist/server-module-plugin/index.js.map +1 -0
  98. package/dist/server-module-plugin/sbom-builder.d.ts +45 -0
  99. package/dist/server-module-plugin/sbom-builder.js +179 -0
  100. package/dist/server-module-plugin/sbom-builder.js.map +1 -0
  101. package/dist/service-portal/angular-provider-plugin.d.ts +2 -0
  102. package/dist/service-portal/angular-provider-plugin.js +78 -0
  103. package/dist/service-portal/angular-provider-plugin.js.map +1 -0
  104. package/dist/service-portal/dependency-plugin.d.ts +2 -0
  105. package/dist/service-portal/dependency-plugin.js +235 -0
  106. package/dist/service-portal/dependency-plugin.js.map +1 -0
  107. package/dist/service-portal/widget-plugin.d.ts +6 -0
  108. package/dist/service-portal/widget-plugin.js +230 -0
  109. package/dist/service-portal/widget-plugin.js.map +1 -0
  110. package/dist/static-content-plugin.d.ts +2 -0
  111. package/dist/static-content-plugin.js +272 -0
  112. package/dist/static-content-plugin.js.map +1 -0
  113. package/dist/table-plugin.d.ts +3 -0
  114. package/dist/table-plugin.js +1324 -0
  115. package/dist/table-plugin.js.map +1 -0
  116. package/dist/ui-action-plugin.d.ts +2 -0
  117. package/dist/ui-action-plugin.js +291 -0
  118. package/dist/ui-action-plugin.js.map +1 -0
  119. package/dist/ui-page-plugin.d.ts +2 -0
  120. package/dist/ui-page-plugin.js +165 -0
  121. package/dist/ui-page-plugin.js.map +1 -0
  122. package/dist/user-preference-plugin.d.ts +15 -0
  123. package/dist/user-preference-plugin.js +63 -0
  124. package/dist/user-preference-plugin.js.map +1 -0
  125. package/dist/utils.d.ts +17 -0
  126. package/dist/utils.js +72 -0
  127. package/dist/utils.js.map +1 -0
  128. package/dist/view-plugin.d.ts +2 -0
  129. package/dist/view-plugin.js +45 -0
  130. package/dist/view-plugin.js.map +1 -0
  131. package/package.json +17 -13
  132. package/src/acl-plugin.ts +256 -0
  133. package/src/application-menu-plugin.ts +109 -0
  134. package/src/arrow-function-plugin.ts +127 -0
  135. package/src/atf/step-configs.ts +2284 -0
  136. package/src/atf/test-plugin.ts +728 -0
  137. package/src/basic-syntax-plugin.ts +729 -0
  138. package/src/business-rule-plugin.ts +266 -0
  139. package/src/call-expression-plugin.ts +202 -0
  140. package/src/client-script-plugin.ts +170 -0
  141. package/src/column/column-helper.ts +119 -0
  142. package/src/column/column-to-record.ts +131 -0
  143. package/src/column-plugin.ts +506 -0
  144. package/src/cross-scope-privilege-plugin.ts +82 -0
  145. package/src/html-import-plugin.ts +79 -0
  146. package/src/index.ts +39 -21
  147. package/src/json-plugin.ts +128 -0
  148. package/src/list-plugin.ts +222 -0
  149. package/src/now-config-plugin.ts +194 -0
  150. package/src/now-id-plugin.ts +78 -0
  151. package/src/now-include-plugin.ts +140 -0
  152. package/src/now-ref-plugin.ts +48 -0
  153. package/src/now-unresolved-plugin.ts +30 -0
  154. package/src/package-json-plugin.ts +87 -0
  155. package/src/property-plugin.ts +118 -0
  156. package/src/record-plugin.ts +171 -0
  157. package/src/repack/index.ts +10 -1
  158. package/src/repack/lint/Rules.ts +5 -4
  159. package/src/repack/lint/index.ts +1 -1
  160. package/src/rest-api-plugin.ts +651 -0
  161. package/src/role-plugin.ts +128 -0
  162. package/src/script-action-plugin.ts +63 -0
  163. package/src/script-include-plugin.ts +110 -0
  164. package/src/server-module-plugin/index.ts +470 -0
  165. package/src/server-module-plugin/sbom-builder.ts +183 -0
  166. package/src/service-portal/angular-provider-plugin.ts +83 -0
  167. package/src/service-portal/dependency-plugin.ts +284 -0
  168. package/src/service-portal/widget-plugin.ts +263 -0
  169. package/src/static-content-plugin.ts +254 -0
  170. package/src/table-plugin.ts +1698 -0
  171. package/src/ui-action-plugin.ts +324 -0
  172. package/src/ui-page-plugin.ts +168 -0
  173. package/src/user-preference-plugin.ts +62 -0
  174. package/src/utils.ts +69 -0
  175. package/src/view-plugin.ts +46 -0
  176. package/dist/AttachmentPlugin.d.ts +0 -254
  177. package/dist/AttachmentPlugin.js +0 -220
  178. package/dist/AttachmentPlugin.js.map +0 -1
  179. package/dist/BusinessRulePlugin.d.ts +0 -30
  180. package/dist/BusinessRulePlugin.js +0 -149
  181. package/dist/BusinessRulePlugin.js.map +0 -1
  182. package/dist/CrossScopePrivilegePlugin.d.ts +0 -35
  183. package/dist/CrossScopePrivilegePlugin.js +0 -80
  184. package/dist/CrossScopePrivilegePlugin.js.map +0 -1
  185. package/dist/DefaultPlugin.d.ts +0 -86
  186. package/dist/DefaultPlugin.js +0 -226
  187. package/dist/DefaultPlugin.js.map +0 -1
  188. package/dist/HtmlTemplatePlugin.d.ts +0 -21
  189. package/dist/HtmlTemplatePlugin.js +0 -29
  190. package/dist/HtmlTemplatePlugin.js.map +0 -1
  191. package/dist/IdPlugin.d.ts +0 -28
  192. package/dist/IdPlugin.js +0 -68
  193. package/dist/IdPlugin.js.map +0 -1
  194. package/dist/IncludePlugin.d.ts +0 -34
  195. package/dist/IncludePlugin.js +0 -155
  196. package/dist/IncludePlugin.js.map +0 -1
  197. package/dist/JsonPlugin.d.ts +0 -28
  198. package/dist/JsonPlugin.js +0 -69
  199. package/dist/JsonPlugin.js.map +0 -1
  200. package/dist/ListPlugin.d.ts +0 -93
  201. package/dist/ListPlugin.js +0 -456
  202. package/dist/ListPlugin.js.map +0 -1
  203. package/dist/NowConfigPlugin.d.ts +0 -45
  204. package/dist/NowConfigPlugin.js +0 -64
  205. package/dist/NowConfigPlugin.js.map +0 -1
  206. package/dist/PackageJsonPlugin.d.ts +0 -34
  207. package/dist/PackageJsonPlugin.js +0 -63
  208. package/dist/PackageJsonPlugin.js.map +0 -1
  209. package/dist/PropertyPlugin.d.ts +0 -51
  210. package/dist/PropertyPlugin.js +0 -181
  211. package/dist/PropertyPlugin.js.map +0 -1
  212. package/dist/ScriptTemplatePlugin.d.ts +0 -13
  213. package/dist/ScriptTemplatePlugin.js +0 -55
  214. package/dist/ScriptTemplatePlugin.js.map +0 -1
  215. package/dist/ServerModulePlugin.d.ts +0 -75
  216. package/dist/ServerModulePlugin.js +0 -368
  217. package/dist/ServerModulePlugin.js.map +0 -1
  218. package/dist/UserPreferencePlugin.d.ts +0 -19
  219. package/dist/UserPreferencePlugin.js +0 -32
  220. package/dist/UserPreferencePlugin.js.map +0 -1
  221. package/dist/aclAndRole/AclPlugin.d.ts +0 -82
  222. package/dist/aclAndRole/AclPlugin.js +0 -262
  223. package/dist/aclAndRole/AclPlugin.js.map +0 -1
  224. package/dist/aclAndRole/RolePlugin.d.ts +0 -66
  225. package/dist/aclAndRole/RolePlugin.js +0 -179
  226. package/dist/aclAndRole/RolePlugin.js.map +0 -1
  227. package/dist/aclAndRole/Util.d.ts +0 -3
  228. package/dist/aclAndRole/Util.js +0 -90
  229. package/dist/aclAndRole/Util.js.map +0 -1
  230. package/dist/app/ApplicationMenuPlugin.d.ts +0 -34
  231. package/dist/app/ApplicationMenuPlugin.js +0 -112
  232. package/dist/app/ApplicationMenuPlugin.js.map +0 -1
  233. package/dist/db/ColumnPlugins.d.ts +0 -750
  234. package/dist/db/ColumnPlugins.js +0 -114
  235. package/dist/db/ColumnPlugins.js.map +0 -1
  236. package/dist/db/DBUtils.d.ts +0 -2
  237. package/dist/db/DBUtils.js +0 -27
  238. package/dist/db/DBUtils.js.map +0 -1
  239. package/dist/db/DocumentationPlugin.d.ts +0 -67
  240. package/dist/db/DocumentationPlugin.js +0 -258
  241. package/dist/db/DocumentationPlugin.js.map +0 -1
  242. package/dist/db/LicensingPlugin.d.ts +0 -60
  243. package/dist/db/LicensingPlugin.js +0 -117
  244. package/dist/db/LicensingPlugin.js.map +0 -1
  245. package/dist/db/RecordPlugin.d.ts +0 -133
  246. package/dist/db/RecordPlugin.js +0 -337
  247. package/dist/db/RecordPlugin.js.map +0 -1
  248. package/dist/db/TablePlugin.d.ts +0 -231
  249. package/dist/db/TablePlugin.js +0 -1628
  250. package/dist/db/TablePlugin.js.map +0 -1
  251. package/dist/db/index.d.ts +0 -6
  252. package/dist/db/index.js +0 -32
  253. package/dist/db/index.js.map +0 -1
  254. package/dist/scriptedRESTAPI/RESTDeserializationUtils.d.ts +0 -10
  255. package/dist/scriptedRESTAPI/RESTDeserializationUtils.js +0 -373
  256. package/dist/scriptedRESTAPI/RESTDeserializationUtils.js.map +0 -1
  257. package/dist/scriptedRESTAPI/RESTSerializationUtils.d.ts +0 -13
  258. package/dist/scriptedRESTAPI/RESTSerializationUtils.js +0 -177
  259. package/dist/scriptedRESTAPI/RESTSerializationUtils.js.map +0 -1
  260. package/dist/scriptedRESTAPI/RestApiPlugin.d.ts +0 -81
  261. package/dist/scriptedRESTAPI/RestApiPlugin.js +0 -345
  262. package/dist/scriptedRESTAPI/RestApiPlugin.js.map +0 -1
  263. package/dist/scriptedRESTAPI/RestSchemaUtils.d.ts +0 -190
  264. package/dist/scriptedRESTAPI/RestSchemaUtils.js +0 -53
  265. package/dist/scriptedRESTAPI/RestSchemaUtils.js.map +0 -1
  266. package/dist/scriptedRESTAPI/RestUtils.d.ts +0 -69
  267. package/dist/scriptedRESTAPI/RestUtils.js +0 -497
  268. package/dist/scriptedRESTAPI/RestUtils.js.map +0 -1
  269. package/dist/scripts/ClientScriptPlugin.d.ts +0 -64
  270. package/dist/scripts/ClientScriptPlugin.js +0 -170
  271. package/dist/scripts/ClientScriptPlugin.js.map +0 -1
  272. package/dist/scripts/scriptUtils.d.ts +0 -1
  273. package/dist/scripts/scriptUtils.js +0 -9
  274. package/dist/scripts/scriptUtils.js.map +0 -1
  275. package/dist/uxf/ExperiencePlugin.d.ts +0 -45
  276. package/dist/uxf/ExperiencePlugin.js +0 -61
  277. package/dist/uxf/ExperiencePlugin.js.map +0 -1
  278. package/dist/uxf/RoutesPlugin.d.ts +0 -29
  279. package/dist/uxf/RoutesPlugin.js +0 -181
  280. package/dist/uxf/RoutesPlugin.js.map +0 -1
  281. package/dist/uxf/UxfFormulaParser/cleanUxValue.d.ts +0 -4
  282. package/dist/uxf/UxfFormulaParser/cleanUxValue.js +0 -65
  283. package/dist/uxf/UxfFormulaParser/cleanUxValue.js.map +0 -1
  284. package/dist/uxf/UxfFormulaParser/grammerParser/api.d.ts +0 -189
  285. package/dist/uxf/UxfFormulaParser/grammerParser/api.js +0 -158
  286. package/dist/uxf/UxfFormulaParser/grammerParser/api.js.map +0 -1
  287. package/dist/uxf/UxfFormulaParser/grammerParser/clientTransformMap.d.ts +0 -13
  288. package/dist/uxf/UxfFormulaParser/grammerParser/clientTransformMap.js +0 -604
  289. package/dist/uxf/UxfFormulaParser/grammerParser/clientTransformMap.js.map +0 -1
  290. package/dist/uxf/UxfFormulaParser/grammerParser/grammarParser.d.ts +0 -12
  291. package/dist/uxf/UxfFormulaParser/grammerParser/grammarParser.js +0 -551
  292. package/dist/uxf/UxfFormulaParser/grammerParser/grammarParser.js.map +0 -1
  293. package/dist/uxf/UxfFormulaParser/grammerParser/spanHelpers.d.ts +0 -31
  294. package/dist/uxf/UxfFormulaParser/grammerParser/spanHelpers.js +0 -64
  295. package/dist/uxf/UxfFormulaParser/grammerParser/spanHelpers.js.map +0 -1
  296. package/dist/uxf/UxfFormulaParser/index.d.ts +0 -3
  297. package/dist/uxf/UxfFormulaParser/index.js +0 -11
  298. package/dist/uxf/UxfFormulaParser/index.js.map +0 -1
  299. package/dist/uxf/UxfFormulaParser/parser.d.ts +0 -8
  300. package/dist/uxf/UxfFormulaParser/parser.js +0 -87
  301. package/dist/uxf/UxfFormulaParser/parser.js.map +0 -1
  302. package/dist/uxf/UxfFormulaParser/utils/getErrorMsg.d.ts +0 -8
  303. package/dist/uxf/UxfFormulaParser/utils/getErrorMsg.js +0 -17
  304. package/dist/uxf/UxfFormulaParser/utils/getErrorMsg.js.map +0 -1
  305. package/dist/uxf/constants.d.ts +0 -2
  306. package/dist/uxf/constants.js +0 -8
  307. package/dist/uxf/constants.js.map +0 -1
  308. package/dist/uxf/index.d.ts +0 -2
  309. package/dist/uxf/index.js +0 -11
  310. package/dist/uxf/index.js.map +0 -1
  311. package/dist/uxf/tectonicIdGenerator.d.ts +0 -12
  312. package/dist/uxf/tectonicIdGenerator.js +0 -79
  313. package/dist/uxf/tectonicIdGenerator.js.map +0 -1
  314. package/src/AttachmentPlugin.ts +0 -268
  315. package/src/BusinessRulePlugin.ts +0 -238
  316. package/src/CrossScopePrivilegePlugin.ts +0 -115
  317. package/src/DefaultPlugin.ts +0 -288
  318. package/src/HtmlTemplatePlugin.ts +0 -31
  319. package/src/IdPlugin.ts +0 -74
  320. package/src/IncludePlugin.ts +0 -206
  321. package/src/JsonPlugin.ts +0 -76
  322. package/src/ListPlugin.ts +0 -570
  323. package/src/NowConfigPlugin.ts +0 -69
  324. package/src/PackageJsonPlugin.ts +0 -68
  325. package/src/PropertyPlugin.ts +0 -237
  326. package/src/ScriptTemplatePlugin.ts +0 -53
  327. package/src/ServerModulePlugin.ts +0 -480
  328. package/src/UserPreferencePlugin.ts +0 -45
  329. package/src/aclAndRole/AclPlugin.ts +0 -420
  330. package/src/aclAndRole/RolePlugin.ts +0 -254
  331. package/src/aclAndRole/Util.ts +0 -113
  332. package/src/app/ApplicationMenuPlugin.ts +0 -165
  333. package/src/db/ColumnPlugins.ts +0 -114
  334. package/src/db/DBUtils.ts +0 -36
  335. package/src/db/DocumentationPlugin.ts +0 -316
  336. package/src/db/LicensingPlugin.ts +0 -138
  337. package/src/db/RecordPlugin.ts +0 -459
  338. package/src/db/TablePlugin.ts +0 -2070
  339. package/src/db/index.ts +0 -6
  340. package/src/scriptedRESTAPI/RESTDeserializationUtils.ts +0 -419
  341. package/src/scriptedRESTAPI/RESTSerializationUtils.ts +0 -228
  342. package/src/scriptedRESTAPI/RestApiPlugin.ts +0 -469
  343. package/src/scriptedRESTAPI/RestSchemaUtils.ts +0 -72
  344. package/src/scriptedRESTAPI/RestUtils.ts +0 -569
  345. package/src/scripts/ClientScriptPlugin.ts +0 -257
  346. package/src/scripts/scriptUtils.ts +0 -5
  347. package/src/uxf/ExperiencePlugin.ts +0 -67
  348. package/src/uxf/RoutesPlugin.ts +0 -211
  349. package/src/uxf/UxfFormulaParser/cleanUxValue.ts +0 -73
  350. package/src/uxf/UxfFormulaParser/grammerParser/api.js +0 -166
  351. package/src/uxf/UxfFormulaParser/grammerParser/clientTransformMap.js +0 -606
  352. package/src/uxf/UxfFormulaParser/grammerParser/grammarParser.js +0 -551
  353. package/src/uxf/UxfFormulaParser/grammerParser/spanHelpers.js +0 -65
  354. package/src/uxf/UxfFormulaParser/index.ts +0 -4
  355. package/src/uxf/UxfFormulaParser/parser.ts +0 -64
  356. package/src/uxf/UxfFormulaParser/utils/getErrorMsg.ts +0 -13
  357. package/src/uxf/constants.ts +0 -4
  358. package/src/uxf/index.ts +0 -2
  359. package/src/uxf/tectonicIdGenerator.ts +0 -78
@@ -0,0 +1,728 @@
1
+ import {
2
+ CallExpressionShape,
3
+ type Diagnostics,
4
+ IdentifierShape,
5
+ ObjectShape,
6
+ Plugin,
7
+ PropertyAccessShape,
8
+ type Record as RecordShape,
9
+ type Shape,
10
+ type Source,
11
+ type StringShape,
12
+ TemplateExpressionShape,
13
+ TemplateSpanShape,
14
+ type TemplateSubstitutions,
15
+ ts,
16
+ UndefinedShape,
17
+ VariableStatementShape,
18
+ } from '@servicenow/sdk-build-core'
19
+ import { NowIdShape } from '../now-id-plugin'
20
+ import { ArrowFunctionShape } from '../arrow-function-plugin'
21
+ import { create } from 'xmlbuilder2'
22
+ import { Test } from '@servicenow/sdk-core/runtime/app'
23
+ import { type ATFVariableInfo, type Category, ToShapeStepConfigs, ToRecordStepConfigs } from './step-configs'
24
+ import { durationFieldToXML, formatDateToPlatformFormat, parseGlideDuration } from '@servicenow/sdk-build-core'
25
+ import type { TimeDuration } from '@servicenow/sdk/core'
26
+
27
+ export const TestPlugin = Plugin.create({
28
+ name: 'TestPlugin',
29
+ records: {
30
+ sys_atf_test: {
31
+ relationships: {
32
+ sys_atf_step: {
33
+ via: 'test',
34
+ descendant: true,
35
+ relationships: {
36
+ sys_variable_value: {
37
+ descendant: true,
38
+ via: 'document_key',
39
+ },
40
+ sys_element_mapping: {
41
+ descendant: true,
42
+ via: 'id',
43
+ },
44
+ },
45
+ },
46
+ },
47
+ toShape(record, { descendants }) {
48
+ const arrowParameter = getArrowFunctionParameter(record)
49
+
50
+ const elementMappingRecords = descendants.query('sys_element_mapping')
51
+ const stepsWhichShouldDeclareAVariable =
52
+ getStepIdsThatAreBeingReferencedByOtherSteps(elementMappingRecords)
53
+ const elementMappingValueMap = getFieldValuesFromElementMappingRecords(elementMappingRecords)
54
+
55
+ const stepRecords = descendants
56
+ .query('sys_atf_step')
57
+ .sort((a, b) => a.get('order').toNumber().getValue() - b.get('order').toNumber().getValue())
58
+
59
+ if (anyStepsAreUnknown(stepRecords, record.get('name').toString().getValue())) {
60
+ return { success: false }
61
+ }
62
+
63
+ const stepVarNames = getVariableNamesForSteps(stepRecords)
64
+
65
+ const statements = stepRecords.map((step) => {
66
+ const stepConfigId = step.get('step_config').toString().getValue()
67
+ const stepId = step.getId().getValue()
68
+ const stepConfig = ToShapeStepConfigs[stepConfigId]!
69
+ const gemIdentifier = stepsWhichShouldDeclareAVariable.has(stepId)
70
+ ? stepVarNames.get(stepId)
71
+ : undefined
72
+
73
+ const variables = descendants
74
+ .query('sys_variable_value', { document: 'sys_atf_step', document_key: stepId })
75
+ .map((svvRecord) => {
76
+ const variableShape = svvRecord.get('variable')
77
+ const variableInfo = stepConfig.variables[variableShape.getValue() as string]
78
+ if (!variableInfo) {
79
+ throw new Error(
80
+ `sys_variable_value variable ${variableShape.getValue()} does not correspond to any known ATF input variables for step type '${stepConfig.name}'`
81
+ )
82
+ }
83
+
84
+ const rawValue =
85
+ elementMappingValueMap.get(`${stepId}:${variableInfo.field}`) ?? svvRecord.get('value')
86
+
87
+ const deserializedValue = serializeValueToShape(
88
+ rawValue?.ifDefined()?.toString().getValue(),
89
+ variableInfo.type
90
+ )
91
+ const value = getElementMappingValues(svvRecord, deserializedValue, stepVarNames)
92
+ if (variableInfo.default !== undefined && value === variableInfo.default) {
93
+ // no need to set the value if its already default
94
+ return undefined
95
+ }
96
+
97
+ const name = variableInfo.name
98
+ return {
99
+ name,
100
+ value,
101
+ }
102
+ })
103
+ .filter((v) => v !== undefined)
104
+ .map((v) => ({ [v.name]: v.value }))
105
+ .reduce((acc, v) => ({ ...acc, ...v }), {})
106
+
107
+ const rawTimeoutValue = step.get('timeout').ifString()?.getValue()
108
+ const timeout = parseGlideDuration(rawTimeoutValue)
109
+
110
+ const callExpression = new CallExpressionShape({
111
+ source: step,
112
+ callee: `${arrowParameter}.${stepConfig?.callName}`,
113
+ args: [
114
+ new ObjectShape({
115
+ source: step,
116
+ properties: step.transform(({ $, merge }) => ({
117
+ $id: $.val(NowIdShape.from(step)),
118
+ active: $.toBoolean().def(true),
119
+ description: $.def(''),
120
+ notes: $.def(''),
121
+ warning: $.from('warning_message').def(''),
122
+ timeout: $.val(timeout),
123
+ [merge]: $.val(variables),
124
+ })),
125
+ }),
126
+ ],
127
+ })
128
+
129
+ return gemIdentifier
130
+ ? new VariableStatementShape({
131
+ source: step,
132
+ variableName: gemIdentifier,
133
+ initializer: callExpression,
134
+ })
135
+ : callExpression
136
+ })
137
+ const arrowFunction =
138
+ statements.length > 0
139
+ ? new ArrowFunctionShape({
140
+ source: record,
141
+ parameters: [arrowParameter],
142
+ statements,
143
+ })
144
+ : undefined
145
+
146
+ return {
147
+ success: true,
148
+ value: new CallExpressionShape({
149
+ source: record,
150
+ callee: Test.name,
151
+ args: [
152
+ record.transform(({ $ }) => ({
153
+ $id: $.val(NowIdShape.from(record)),
154
+ name: $,
155
+ description: $.def(''),
156
+ active: $.toBoolean().def(true),
157
+ failOnServerError: $.from('fail_on_server_error').toBoolean().def(false),
158
+ })),
159
+ arrowFunction,
160
+ ].filter((arg) => arg),
161
+ }),
162
+ }
163
+ },
164
+ },
165
+ sys_variable_value: {
166
+ coalesce: ['document', 'document_key', 'variable'],
167
+ },
168
+ sys_atf_step: {
169
+ toFile(step, { database }) {
170
+ const recordUpdate = create().ele('record_update', { table: 'sys_atf_step' })
171
+ const stepElement = recordUpdate.ele('sys_atf_step', { action: 'INSERT_OR_UPDATE' })
172
+ const stepId = step.getId().getValue()
173
+ if (!stepId) {
174
+ throw new Error('Invalid step id')
175
+ }
176
+
177
+ stepElement.ele('sys_id').txt(stepId)
178
+
179
+ Object.entries(step.properties()).forEach(([key, value]) => {
180
+ stepElement.ele(key).txt(value.ifDefined()?.toString()?.getValue() ?? '')
181
+ })
182
+
183
+ const variableValues = database.query('sys_variable_value', {
184
+ document: 'sys_atf_step',
185
+ document_key: step.getId(),
186
+ })
187
+
188
+ recordUpdate.ele('sys_variable_value', {
189
+ action: 'delete_multiple',
190
+ query: `document_key=${stepId}`,
191
+ })
192
+
193
+ variableValues.forEach((varRecord) => {
194
+ const variableElement = recordUpdate.ele('sys_variable_value', { action: 'INSERT_OR_UPDATE' })
195
+ variableElement.ele('sys_id').txt(varRecord.getId().getValue())
196
+ Object.entries(varRecord.properties()).forEach(([key, value]) => {
197
+ variableElement.ele(key).txt(value instanceof UndefinedShape ? '' : value.toString().getValue())
198
+ })
199
+ })
200
+
201
+ const elementMappingRecords = database.query('sys_element_mapping', { id: stepId })
202
+ if (elementMappingRecords.length > 0) {
203
+ recordUpdate.ele('sys_element_mapping', {
204
+ action: 'delete_multiple',
205
+ query: `id=${stepId}`,
206
+ })
207
+ }
208
+
209
+ elementMappingRecords.forEach((record) => {
210
+ const elementMappingElement = recordUpdate.ele('sys_element_mapping', {
211
+ action: 'INSERT_OR_UPDATE',
212
+ })
213
+ elementMappingElement.ele('sys_id').txt(record.getId().getValue())
214
+ Object.entries(record.properties()).forEach(([key, value]) => {
215
+ elementMappingElement.ele(key).txt(value.toString().getValue())
216
+ })
217
+ })
218
+
219
+ return {
220
+ success: true,
221
+ value: {
222
+ name: `sys_atf_step_${step.getId().getValue()}.xml`,
223
+ category: step.getInstallCategory(),
224
+ content: recordUpdate.end({ prettyPrint: true }),
225
+ },
226
+ }
227
+ },
228
+ },
229
+ sys_element_mapping: {
230
+ coalesce: ['field', 'id'],
231
+ },
232
+ },
233
+ shapes: [
234
+ {
235
+ shape: CallExpressionShape,
236
+ fileTypes: ['fluent'],
237
+ async toRecord(callExpression, { factory, diagnostics }) {
238
+ if (callExpression.getCallee() !== Test.name) {
239
+ return { success: false }
240
+ }
241
+
242
+ const prop = callExpression.getArgument(0).asObject()
243
+ const arrowFunc = callExpression.getArgument(1).if(ArrowFunctionShape)
244
+ const testId = prop.get('$id')
245
+
246
+ const steps = arrowFunc ? getStepInfoFromArrowFunction(arrowFunc, diagnostics) : []
247
+ if (steps.some((step) => !step)) {
248
+ return { success: false }
249
+ }
250
+
251
+ const testRecord = factory.createRecord({
252
+ source: callExpression,
253
+ table: 'sys_atf_test',
254
+ explicitId: testId,
255
+ properties: prop.transform(({ $ }) => ({
256
+ name: $,
257
+ active: $.def(true),
258
+ description: $.def(''),
259
+ fail_on_server_error: $.from('failOnServerError').def(false),
260
+ })),
261
+ })
262
+
263
+ const stepRecords = steps.map((step, index) => {
264
+ const rawTimeout = step.values.get('timeout')
265
+ const timeout = rawTimeout.isUndefined()
266
+ ? step.defaultTimeout
267
+ : convertTimeoutToSystemFormat(rawTimeout)
268
+
269
+ return factory.createRecord({
270
+ table: 'sys_atf_step',
271
+ source: step.source,
272
+ explicitId: step.values.get('$id'),
273
+ properties: step.values.transform(({ $ }) => ({
274
+ active: $.toBoolean().def(true),
275
+ description: $,
276
+ display_name: $.val(step.displayName),
277
+ notes: $,
278
+ order: $.val(index + 1),
279
+ step_config: $.val(step.stepConfigId),
280
+ table: $.val(step.table),
281
+ test: $.val(testRecord.getId()),
282
+ timeout: $.val(timeout),
283
+ warning_message: $.from('warning'),
284
+ })),
285
+ })
286
+ })
287
+
288
+ const stepAndVariableValueRecords = steps.flatMap((step, index) => {
289
+ const variableRecords: RecordShape[] = Object.entries(step.variables).flatMap(
290
+ ([varName, atfVariableInfo]) => {
291
+ const valueShape = step.values.get(varName, false)
292
+
293
+ let elementMappingRecord: RecordShape | undefined
294
+
295
+ const value = createGemExpressionsFromShape(valueShape, stepRecords, diagnostics)
296
+ if (value !== undefined) {
297
+ elementMappingRecord = factory.createRecord({
298
+ table: 'sys_element_mapping',
299
+ source: step.source,
300
+ properties: {
301
+ field: atfVariableInfo.field,
302
+ id: stepRecords[index]?.getId(),
303
+ table: `var__m_atf_input_variable_${step.stepConfigId}`,
304
+ value: serializeValueToRecord(
305
+ value,
306
+ atfVariableInfo.type,
307
+ atfVariableInfo.default
308
+ ),
309
+ },
310
+ })
311
+ }
312
+
313
+ return [
314
+ factory.createRecord({
315
+ table: 'sys_variable_value',
316
+ source: step.source,
317
+ properties: {
318
+ document: 'sys_atf_step',
319
+ document_key: stepRecords[index]?.getId(),
320
+ value: serializeValueToRecord(
321
+ value ??
322
+ valueShape.ifResolvable()?.resolve().ifRecord()?.getId().getValue() ??
323
+ valueShape.getValue(),
324
+ atfVariableInfo.type,
325
+ atfVariableInfo.default
326
+ ),
327
+ variable: atfVariableInfo.inputVariableId,
328
+ order: atfVariableInfo.order,
329
+ },
330
+ }),
331
+ ...(elementMappingRecord ? [elementMappingRecord] : []),
332
+ ]
333
+ }
334
+ )
335
+
336
+ return variableRecords
337
+ })
338
+
339
+ return {
340
+ success: true,
341
+ value: testRecord.with(...stepRecords, ...stepAndVariableValueRecords),
342
+ }
343
+ },
344
+ },
345
+ ],
346
+ })
347
+
348
+ const UNSUPPORTED_STEP_CONFIGS = {
349
+ '38907e937322130007d738682bf6a742': 'Component State Validation (Custom UI)',
350
+ '475e0de3d732130089fca2285e610361': 'Assert Text on Page (Custom UI)',
351
+ b4758c7453370300c792ddeeff7b128d: 'Component Value Validation (Custom UI)',
352
+ def25c4b73730300c79260bdfaf6a700: 'Click Component (Custom UI)',
353
+ e5dd168473330300c79260bdfaf6a794: 'Set Component Values (Custom UI)',
354
+ fc7e65d577332300e46abe41a9106106: 'Open Service Portal Page',
355
+ '012105620fe2330091d0f00c97767ec4': 'Validate List UI Action Visibility',
356
+ '0200ac2fe72003005c85cd19d2f6a942': 'Open a Record in List',
357
+ '7bdce31387400300709861fb97cb0b5a': 'Validate Record Present in List',
358
+ '8b84e5e837b1030064a52f3c8e41f170': 'Validate Related List Visibility',
359
+ a69843f2531332007e7829cac2dc34d7: 'Apply Filter to List',
360
+ c5f44934532332007e7829cac2dc342e: 'Click a List UI Action',
361
+ }
362
+
363
+ function getFieldValuesFromElementMappingRecords(elementMappingRecords: RecordShape[]) {
364
+ return elementMappingRecords
365
+ .filter((em) => em.get('value').getValue())
366
+ .reduce((map, em) => {
367
+ const field = em.get('field').getValue()
368
+ const stepId = em.get('id').getValue()
369
+ return map.set(`${stepId}:${field}`, em.get('value'))
370
+ }, new Map<string, Shape>())
371
+ }
372
+
373
+ function convertTimeoutToSystemFormat(timeoutShape: Shape) {
374
+ const timeoutDuration = timeoutShape.ifObject()?.getValue() as TimeDuration | undefined
375
+ const timeoutDate = timeoutDuration && durationFieldToXML(timeoutDuration)
376
+ return timeoutDate && formatDateToPlatformFormat(timeoutDate)
377
+ }
378
+
379
+ function anyStepsAreUnknown(stepRecords: RecordShape[], testName: string) {
380
+ return stepRecords.some((stepRecord) => {
381
+ const stepConfigId = stepRecord.get('step_config').toString().getValue()
382
+ if (!ToShapeStepConfigs[stepConfigId]) {
383
+ const stepConfigName = UNSUPPORTED_STEP_CONFIGS[stepConfigId] ?? stepConfigId
384
+ console.error(
385
+ `Unable to transform ATF test '${testName}' because of unsupported step_config: '${stepConfigName}'`
386
+ )
387
+ return true
388
+ }
389
+ return false
390
+ })
391
+ }
392
+
393
+ function getArrowFunctionParameter(record: RecordShape) {
394
+ const source = record.getOriginalSource()
395
+
396
+ return (
397
+ (ts.Node.isNode(source) &&
398
+ source.isKind(ts.SyntaxKind.CallExpression) &&
399
+ source.getArguments()[1]?.asKind(ts.SyntaxKind.ArrowFunction)?.getParameters()[0]?.getName()) ||
400
+ 'atf'
401
+ )
402
+ }
403
+
404
+ function propertyAccessToGemExpression(
405
+ propertyAccess: PropertyAccessShape,
406
+ stepRecords: RecordShape[],
407
+ diagnostics: Diagnostics
408
+ ) {
409
+ const split = propertyAccess.getCode().split('.')
410
+ if (!split[0]) {
411
+ diagnostics.error(propertyAccess, `Invalid expression`)
412
+ return undefined
413
+ }
414
+
415
+ const sourceStep = stepRecords.find(
416
+ (rec) => rec.getSource() === propertyAccess.getFirstElement().resolve().if(CallExpressionShape)
417
+ )
418
+ if (!sourceStep) {
419
+ diagnostics.error(propertyAccess, `Invalid expression, expecting a reference to an ATF step`)
420
+ }
421
+
422
+ const stepId = sourceStep?.getId().getValue()
423
+ const elementPath = split.slice(1).join('.')
424
+ const suffix = elementPath ? `.${elementPath}` : ''
425
+
426
+ return `{{step['${stepId}']${suffix}}}`
427
+ }
428
+
429
+ function createGemExpressionsFromShape(shape: Shape, stepRecords: RecordShape[], diagnostics: Diagnostics) {
430
+ if (shape instanceof PropertyAccessShape) {
431
+ return propertyAccessToGemExpression(shape, stepRecords, diagnostics)
432
+ }
433
+ if (shape instanceof TemplateExpressionShape) {
434
+ const gemExpressions = shape
435
+ .getSpans()
436
+ .map((span) =>
437
+ propertyAccessToGemExpression(span.getExpression().as(PropertyAccessShape), stepRecords, diagnostics)
438
+ )
439
+ .reduce((acc, gemExpression, index) => ({ ...acc, [index]: gemExpression }), {}) as TemplateSubstitutions
440
+
441
+ return shape.getValue(gemExpressions)
442
+ }
443
+
444
+ if (shape instanceof ObjectShape) {
445
+ const obj = {}
446
+ let gemExpressionFound = false
447
+ for (const key in shape.properties()) {
448
+ const value = createGemExpressionsFromShape(shape.get(key, false), stepRecords, diagnostics)
449
+ gemExpressionFound = gemExpressionFound || value !== undefined
450
+ obj[key] = value || shape.get(key).getValue()
451
+ }
452
+ return gemExpressionFound ? obj : undefined
453
+ }
454
+
455
+ return undefined
456
+ }
457
+
458
+ function getStepInfoFromArrowFunction(arrowFunc: ArrowFunctionShape, diagnostics: Diagnostics) {
459
+ return arrowFunc
460
+ .getStatements()
461
+ .filter((statement) => statement instanceof CallExpressionShape || statement instanceof VariableStatementShape)
462
+ .map((statement) => getStepInfoFromAtfCallExpression(statement, diagnostics))
463
+ .filter((step) => step) as StepInfo[]
464
+ }
465
+
466
+ type StepInfo = {
467
+ displayName: string
468
+ source: Source
469
+ stepConfigId: string
470
+ table: StringShape | undefined
471
+ variables: Record<string, ATFVariableInfo>
472
+ values: ObjectShape
473
+ identifier: string | undefined
474
+ defaultTimeout?: string
475
+ }
476
+
477
+ function getStepInfoFromAtfCallExpression(
478
+ statement: CallExpressionShape | VariableStatementShape,
479
+ diagnostics: Diagnostics
480
+ ): StepInfo | undefined {
481
+ let callExpression: CallExpressionShape
482
+ let identifier: string | undefined
483
+ if (statement instanceof VariableStatementShape) {
484
+ callExpression = statement.getInitializer() as CallExpressionShape
485
+ identifier = statement.getVariableName().getName()
486
+ } else if (statement instanceof CallExpressionShape) {
487
+ callExpression = statement
488
+ } else {
489
+ return undefined
490
+ }
491
+
492
+ const [, category, funcName] = callExpression.getCallee().split('.')
493
+ if (!category || !funcName) {
494
+ diagnostics.info(callExpression, 'Invalid ATF step')
495
+ return undefined
496
+ }
497
+
498
+ if (!ToRecordStepConfigs[category]) {
499
+ diagnostics.warn(callExpression, `Unknown category: ${category}`)
500
+ return undefined
501
+ }
502
+
503
+ if (!ToRecordStepConfigs[category][funcName]) {
504
+ diagnostics.warn(callExpression, `Unknown step: ${funcName}`)
505
+ return undefined
506
+ }
507
+
508
+ const stepConfig = ToRecordStepConfigs[category as Category][funcName]!
509
+ const values = callExpression.getArgument(0).asObject()
510
+ return {
511
+ displayName: stepConfig.name,
512
+ stepConfigId: stepConfig.stepConfigId,
513
+ variables: stepConfig.variables,
514
+ table: values.get('table')?.ifString(),
515
+ source: callExpression,
516
+ identifier,
517
+ defaultTimeout: stepConfig.defaultTimeout,
518
+ values,
519
+ }
520
+ }
521
+
522
+ function getVariableNamesForSteps(stepRecords: RecordShape[]) {
523
+ return stepRecords.reduce((map, step, index) => {
524
+ const source = step.getOriginalSource()
525
+ const name =
526
+ (ts.Node.isNode(source) && source.getParentIfKind(ts.SyntaxKind.VariableDeclaration)?.getName()) ||
527
+ `step${index + 1}`
528
+
529
+ return map.set(step.getId().getValue(), name)
530
+ }, new Map<string, string>())
531
+ }
532
+
533
+ const GemRegex = /{{step\[(?:'|.{6})(?<stepId>[0-9a-f]{32})(?:'|.{6})\]\.(?<elementPath>.*?)}}/gm
534
+
535
+ function getStepIdsThatAreBeingReferencedByOtherSteps(elementMappingRecord: RecordShape[]) {
536
+ return elementMappingRecord
537
+ .flatMap((rec) => {
538
+ const str = rec.get('value').toString().getValue()
539
+ const matches = str.matchAll(GemRegex)
540
+
541
+ return Array.from(matches).map((m) => {
542
+ const [, stepId] = m
543
+ return stepId
544
+ })
545
+ })
546
+ .filter((stepId) => stepId !== undefined)
547
+ .reduce((acc, stepId) => acc.add(stepId), new Set<string>())
548
+ }
549
+
550
+ function variableElementPathToPropertyAccess(source: Source, propertyAccessPath: string) {
551
+ const elements = propertyAccessPath.split('.').map((e) => new IdentifierShape({ source, name: e }))
552
+
553
+ return new PropertyAccessShape({
554
+ source,
555
+ elements: [elements[0], elements[1], ...elements.slice(2)],
556
+ })
557
+ }
558
+
559
+ function getElementMappingValues(source: Source, value: any, stepIdToVarName: Map<string, string>) {
560
+ if (typeof value === 'object' && value !== null) {
561
+ if (Array.isArray(value)) {
562
+ return value.map((v) => getElementMappingValues(source, v, stepIdToVarName))
563
+ } else {
564
+ const obj = {}
565
+ for (const key in value) {
566
+ obj[key] = getElementMappingValues(source, value[key], stepIdToVarName)
567
+ }
568
+ return obj
569
+ }
570
+ }
571
+
572
+ const potentialGemExpression = typeof value === 'string' ? value : undefined
573
+ if (!potentialGemExpression) {
574
+ return value
575
+ }
576
+
577
+ const [matched] = Array.from(potentialGemExpression.matchAll(GemRegex))
578
+ const simpleGemExpression = matched && matched[0] === potentialGemExpression
579
+ if (!matched) {
580
+ return value
581
+ }
582
+
583
+ // If the GEM expression is simple, it only contains the GEM
584
+ // expression and nothing else. This means we can transform it
585
+ // a PropertyAccessExpression, otherwise we'll need to create
586
+ // a TemplateExpression
587
+ if (simpleGemExpression) {
588
+ const stepId = matched.groups!['stepId']!
589
+ const elementPath = matched.groups?.['elementPath']
590
+ const varName = stepIdToVarName.get(stepId)
591
+ if (!varName) {
592
+ return undefined
593
+ }
594
+ const lastIdentifier = elementPath?.split('.')[0]
595
+ if (!lastIdentifier) {
596
+ throw new Error(`Invalid GEM expression found in: '${potentialGemExpression}'`)
597
+ }
598
+
599
+ return variableElementPathToPropertyAccess(source, `${varName}.${elementPath}`)
600
+ }
601
+
602
+ const matches = Array.from(potentialGemExpression.matchAll(GemRegex))
603
+ if (!matches[0]) {
604
+ return undefined
605
+ }
606
+
607
+ const spans: TemplateSpanShape[] = []
608
+ const head = potentialGemExpression.substring(0, matches[0].index)
609
+
610
+ for (let i = 0; i < matches.length; i++) {
611
+ const m = matches[i]!
612
+ const gem = m[0]
613
+
614
+ const nextGemIndex = matches[i + 1]?.index
615
+ const tail = potentialGemExpression.substring(m.index + gem.length, nextGemIndex)
616
+ const stepId = m.groups?.['stepId'] as string
617
+ const elementPath = m.groups?.['elementPath'] ?? ''
618
+ const varName = stepIdToVarName.get(stepId)
619
+
620
+ spans.push(
621
+ new TemplateSpanShape({
622
+ source,
623
+ literalText: tail,
624
+ expression: variableElementPathToPropertyAccess(source, `${varName}.${elementPath}`),
625
+ })
626
+ )
627
+ }
628
+
629
+ return new TemplateExpressionShape({
630
+ source,
631
+ literalText: head,
632
+ spans: spans,
633
+ })
634
+ }
635
+
636
+ function objectToEncodedQuery(objectShape: Record<string, any>) {
637
+ return Object.entries(objectShape)
638
+ .map(([key, value]) => {
639
+ const escapedValue = value.toString().replaceAll('^', '^^')
640
+ return `${key}=${escapedValue}`
641
+ })
642
+ .concat('EQ')
643
+ .join('^')
644
+ }
645
+
646
+ export function serializeValueToRecord(value: any, type: string, defaultValue: any) {
647
+ value = value === undefined ? defaultValue : value
648
+
649
+ switch (type) {
650
+ case 'field_list':
651
+ case 'glide_list':
652
+ return Array.isArray(value) ? value.join(',') : value
653
+ case 'string': {
654
+ return value ? value : undefined
655
+ }
656
+ case 'simple_name_values': {
657
+ if (typeof value !== 'object' || value === null || Object.keys(value).length === 0) {
658
+ return ''
659
+ }
660
+ return JSON.stringify(value)
661
+ }
662
+ case 'template_value':
663
+ return value && objectToEncodedQuery(value)
664
+ case 'boolean':
665
+ return value ? 1 : 0
666
+ default:
667
+ return value
668
+ }
669
+ }
670
+
671
+ function convertToPrimitiveValue(value: string) {
672
+ if (value === '') {
673
+ return value
674
+ }
675
+
676
+ if (value === 'true') {
677
+ return true
678
+ }
679
+
680
+ if (value === 'false') {
681
+ return false
682
+ }
683
+
684
+ const maybeNumber = Number(value)
685
+ if (!isNaN(maybeNumber)) {
686
+ return maybeNumber
687
+ }
688
+
689
+ return value
690
+ }
691
+
692
+ function queryToFieldValues(query: string) {
693
+ const caratReplacement = '__CARATREPLACEMENTSTRING__'
694
+ return query
695
+ .replaceAll('^^', caratReplacement)
696
+ .split('^')
697
+ .filter((term) => term !== 'EQ')
698
+ .map((term) => term.split('='))
699
+ .filter(([, value]) => value !== undefined)
700
+ .map(([key, value]) => ({ [key as string]: convertToPrimitiveValue(value!.replaceAll(caratReplacement, '^')) }))
701
+ .reduce((acc, obj) => ({ ...acc, ...obj }), {})
702
+ }
703
+
704
+ export function serializeValueToShape(value: string | undefined, type: string) {
705
+ if (value === undefined) {
706
+ return value
707
+ }
708
+ switch (type) {
709
+ case 'integer':
710
+ return value ? parseInt(value, 10) : undefined
711
+ case 'glide_list':
712
+ case 'field_list':
713
+ if (!value) {
714
+ return undefined
715
+ }
716
+ return typeof value === 'string' ? value.split(',') : value
717
+ case 'document_id':
718
+ return value ? value : undefined
719
+ case 'simple_name_values':
720
+ return value ? JSON.parse(value) : undefined
721
+ case 'template_value':
722
+ return queryToFieldValues(value)
723
+ case 'boolean':
724
+ return value === '1'
725
+ default:
726
+ return value
727
+ }
728
+ }