@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
@@ -1,2070 +0,0 @@
1
- import {
2
- ChoiceConfig,
3
- Table,
4
- Record as NowRecord,
5
- TableName,
6
- choiceDropdown,
7
- DateColumn,
8
- BasicDateTimeColumn,
9
- GenericColumn,
10
- BooleanColumn,
11
- ChoiceColumn,
12
- IntegerDateColumn,
13
- ScheduleDateTimeColumn,
14
- ConditionsColumn,
15
- DateTimeColumn,
16
- CalendarDateTimeColumn,
17
- DueDateColumn,
18
- OtherDateColumn,
19
- DecimalColumn,
20
- DocumentIdColumn,
21
- DomainIdColumn,
22
- DomainPathColumn,
23
- FieldNameColumn,
24
- IntegerColumn,
25
- RadioColumn,
26
- ReferenceColumn,
27
- ScriptColumn,
28
- SystemClassNameColumn,
29
- TableNameColumn,
30
- TranslatedFieldColumn,
31
- TranslatedTextColumn,
32
- UserRolesColumn,
33
- VersionColumn,
34
- StringColumn,
35
- Documentation,
36
- ListColumn,
37
- BasicImageColumn,
38
- } from '@servicenow/sdk-core/runtime/db'
39
- import {
40
- Context,
41
- EntityData,
42
- LinkedDocument,
43
- Plugin,
44
- extractCallExpression,
45
- getCallExpressionName,
46
- getOrCreateEntitySourceFile,
47
- getOrCreatePropertyAssignment,
48
- linkDocument,
49
- removeNode,
50
- stringify,
51
- transformFunctionArguments,
52
- XmlData,
53
- FluentDiagnostic,
54
- generateCallExpression,
55
- createPropertyIdentifier,
56
- ObjectData,
57
- isSNScope,
58
- GUID,
59
- mergeDataIntoObjectLiteral,
60
- getPropertyAssignment,
61
- mergeDataIntoObjectLiteralArray,
62
- addNamedImportIfAbsent,
63
- generateCallExpressionExportForDocument,
64
- Document,
65
- generateCallExpressionExport,
66
- PartialElements,
67
- getObjectPropertyAssignmentName,
68
- } from '@servicenow/sdk-build-core'
69
- import { create } from 'xmlbuilder2'
70
- import { isArray, isEmpty, isObject, parseInt } from 'lodash'
71
- import { z } from 'zod'
72
- import { RecordPlugin, TextBooleanSchema, TextNumberSchema, TextStringSchema } from './RecordPlugin'
73
- import { Diagnostic, ts, tsc } from '@servicenow/sdk-project'
74
- import { XMLBuilder } from 'xmlbuilder2/lib/interfaces'
75
- import { getLabelDiagnostics } from './DBUtils'
76
- import { ModuleFunctionData } from '../ServerModulePlugin'
77
-
78
- /**
79
- * The access levels are mapped to the following values on the platform
80
- *
81
- * - `none`: 0
82
- * - `tracking`: 1
83
- * - `restricted`: 2
84
- *
85
- */
86
- const callerAccess = ['none', 'tracking', 'restricted'] as const
87
-
88
- // Basic info needed for table references
89
- const TableSchemaFull = z.object({
90
- /** lowercase, one word name. Numbers, letters and underscores only */
91
- name: z.string(),
92
- /** Object literal of column names with <type>Column() calls as values.
93
- * Ex. { column_name_1: StringColumn({...args}), column_name_2: IntegerColumn({...args}), }
94
- * Import column definitions from `@servicenow/sdk-core/db`
95
- */
96
- schema: z.record(z.record(z.any())).default({}),
97
- /** Table as a string, this table will inherit schema from extends table.
98
- * Escape with `` (import from `@servicenow/sdk-core/global`)
99
- * if table definition not present locally */
100
- extends: z.string().optional(),
101
- /** Will match name if not provided */
102
- label: z.string().or(z.array(z.any())).optional(),
103
- /** Must match column name */
104
- display: z.string().optional(),
105
-
106
- // Controls
107
- extensible: z.boolean().optional().default(false),
108
- live_feed: z.boolean().optional().default(false),
109
-
110
- /** sys_number to create auto prefixing. Specify as Object literal */
111
- auto_number: z
112
- .object({
113
- prefix: z.string().default('pre').optional(),
114
- number: z.number().default(1000).optional(),
115
- number_of_digits: z.number().default(7).optional(),
116
- })
117
-
118
- .optional(),
119
-
120
- // Application Access
121
- accessible_from: z
122
- .union([z.literal('package_private'), z.literal('public')])
123
- .optional()
124
- .default('public'),
125
- caller_access: z.enum(callerAccess).optional(),
126
- /** Array of read, update, create, delete actions (['read', 'update',...])*/
127
- actions: z
128
- .array(z.union([z.literal('read'), z.literal('update'), z.literal('delete'), z.literal('create')]))
129
- .optional(),
130
-
131
- allow_web_service_access: z.boolean().optional().default(false),
132
- allow_new_fields: z.boolean().optional().default(false),
133
- allow_ui_actions: z.boolean().optional().default(false),
134
- allow_client_scripts: z.boolean().optional().default(false),
135
-
136
- // From sys_dictionary
137
- audit: z.boolean().optional().default(false),
138
- read_only: z.boolean().optional().default(false),
139
- text_index: z.boolean().optional().default(false),
140
-
141
- /** Object literal of key value pairs corresponding to attributes */
142
- attributes: z.record(z.union([z.string(), z.number(), z.boolean()])).optional(),
143
-
144
- /** Array of objects [{ { name: <columnName>, element: ...,}...}] */
145
- index: z
146
- .array(
147
- z.object({
148
- name: z.string(),
149
- unique: z.boolean(),
150
- element: z
151
- .string()
152
- .or(z.array(z.string()))
153
- .transform((el) => (isArray(el) ? el : [el])),
154
- })
155
- )
156
- .optional(),
157
-
158
- licensing_config: z.record(z.any()).optional(),
159
- scriptable_table: z.boolean().default(false),
160
- })
161
-
162
- const componentTables = ['sys_dictionary', 'sys_choice', 'sys_documentation', 'ua_table_licensing_config']
163
-
164
- type IndexType = {
165
- name: string
166
- unique: boolean
167
- element: string[] | string
168
- }
169
-
170
- // Everything that goes into a table
171
- // Everything which goes into a element with type='string/int/etc' in bootstrap.xml
172
- type ColumnSchema = z.infer<typeof ColumnSchema>
173
- const ColumnSchema = z.object({
174
- entityKind: z.string().optional(),
175
- column_type: z.string().optional(),
176
- audit: z.boolean().optional().default(false),
177
- label: z.string().or(z.array(z.any())).optional(),
178
- maxLength: z.number().optional(),
179
- mandatory: z.boolean().optional().default(false),
180
- read_only: z.boolean().optional().default(false),
181
- default: z.any().optional(),
182
- attributes: z.record(z.string(), z.union([z.string(), z.boolean(), z.number()])).optional(),
183
- referenceTable: z.string().optional(),
184
- cascadeRule: z.string().optional(),
185
- dropdown: z.enum(choiceDropdown).default('none').optional(),
186
- choices: z.record(z.any()).or(z.array(z.any())).optional(),
187
- choice_elements: z.record(z.any()).or(z.array(z.any())).optional(),
188
- display: z.boolean().default(false).optional(),
189
- function_definition: z.string().optional(),
190
- dynamic_value_definitions: z
191
- .object({
192
- type: z.union([
193
- z.literal('dynamic_default'),
194
- z.literal('choices_from_other_table'),
195
- z.literal('calculated_value'),
196
- z.literal('dependent_field'),
197
- ]),
198
- })
199
- .and(z.any())
200
- .optional(),
201
- plural: z.string().optional(),
202
- hint: z.string().optional(),
203
- help: z.string().optional(),
204
- widget: z.string().optional(),
205
- table_reference: z.boolean().optional(),
206
- reference_floats: z.boolean().optional(),
207
- dynamic_creation: z.boolean().optional(),
208
- dynamic_creation_script: z.string().optional(),
209
- element_reference: z.boolean().optional(),
210
- spell_check: z.boolean().optional(),
211
- xml_view: z.boolean().optional(),
212
- array: z.boolean().optional(),
213
- text_index: z.boolean().optional(),
214
- primary: z.boolean().optional(),
215
- unique: z.boolean().optional(),
216
- reference_key: z.string().optional(),
217
- reference_qual: z.string().optional(),
218
- })
219
-
220
- const BooleanFromString = z
221
- .string()
222
- .transform((str) => str === 'true')
223
- .or(z.boolean())
224
- .optional()
225
-
226
- const IntFromString = z
227
- .string()
228
- .transform((str) => parseInt(str))
229
- .or(z.number())
230
- .optional()
231
-
232
- // These fields transform from sys_db_object only, not bootstrap. (Except name, which is needed to match)
233
- const DBObjectIncomingAttributes = z.object({
234
- name: TextStringSchema.or(z.string()).optional(),
235
-
236
- read_access: TextBooleanSchema.or(BooleanFromString).optional(),
237
- create_access: TextBooleanSchema.or(BooleanFromString).optional(),
238
- update_access: TextBooleanSchema.or(BooleanFromString).optional(),
239
- delete_access: TextBooleanSchema.or(BooleanFromString).optional(),
240
-
241
- ws_access: TextBooleanSchema.or(BooleanFromString).optional(),
242
- caller_access: TextNumberSchema.or(IntFromString)
243
- .transform((val) => {
244
- if (val) {
245
- return callerAccess[val]
246
- }
247
- return
248
- })
249
- .optional(),
250
- alter_access: TextBooleanSchema.or(BooleanFromString).optional(),
251
- client_scripts_access: TextBooleanSchema.or(BooleanFromString).optional(),
252
- actions_access: TextBooleanSchema.or(BooleanFromString).optional(),
253
- //configuration_access: TextBooleanSchema.or(BooleanFromString).optional().default(false),
254
-
255
- is_extendable: TextBooleanSchema.or(BooleanFromString).optional(),
256
- // live_feed_enabled: TextBooleanSchema.or(BooleanFromString).optional().default(false),
257
-
258
- access: TextStringSchema.or(z.string()).optional(),
259
-
260
- scriptable_table: TextBooleanSchema.or(BooleanFromString).optional(),
261
- })
262
-
263
- // Attributes in the element='collection' tag of bootstrap xml
264
- const TableSchemaBootstrap = z.object({
265
- name: z.string(),
266
- extends: z.string().optional(),
267
- label: z.string().or(z.array(z.any())).optional(),
268
-
269
- // Controls
270
- extensible: z.boolean().optional().default(false),
271
- live_feed: z.boolean().optional().default(false),
272
-
273
- auto_number: z
274
- .object({
275
- prefix: z.string().default('pre').optional(),
276
- number: z.number().default(1000).optional(),
277
- number_of_digits: z.number().default(7).optional(),
278
- })
279
- .optional(),
280
-
281
- number_ref: z.any().optional(),
282
-
283
- // Application Access
284
- accessible_from: z
285
- .union([z.literal('public'), z.literal('package_private')])
286
- .optional()
287
- .default('public'),
288
- caller_access: z.enum(callerAccess).default('none').optional(),
289
-
290
- actions: z
291
- .array(z.union([z.literal('read'), z.literal('update'), z.literal('delete'), z.literal('create')]))
292
- .default(['read'])
293
- .optional(),
294
-
295
- allow_web_service_access: z.boolean().optional().default(true),
296
- allow_new_fields: z.boolean().optional().default(false),
297
- allow_ui_actions: z.boolean().optional().default(false),
298
- allow_client_scripts: z.boolean().optional().default(false),
299
-
300
- // From sys_dictionary
301
- audit: z.boolean().optional().default(false),
302
- read_only: z.boolean().optional().default(false),
303
- text_index: z.boolean().optional().default(false),
304
-
305
- scriptable_table: z.boolean().optional().default(false),
306
-
307
- attributes: z
308
- .record(z.union([z.string(), z.number(), z.boolean()]))
309
- .default({})
310
- .optional(),
311
- })
312
-
313
- const TableSchemaBootstrapIncoming = TableSchemaBootstrap.omit({ actions: true }).extend({
314
- caller_access: z
315
- .union([z.literal(0), z.literal(1), z.literal(2)])
316
- .transform((val) => {
317
- if (val) {
318
- return callerAccess[val]
319
- }
320
- return
321
- })
322
- .optional(),
323
- accessible_from: z.union([z.literal('public'), z.literal('package_private')]).optional(),
324
- extends: z
325
- .string()
326
- .or(z.object({ name: z.string() }).transform((obj) => obj.name))
327
- .optional(),
328
- live_feed: z.boolean().optional().default(false),
329
- index: z.any().optional(),
330
- columns: z.any().optional(),
331
- })
332
-
333
- // Everything in side <database> in boostrap.xml
334
- const BootstrapDatabaseElement = z.object({
335
- element: z.record(z.any()),
336
- })
337
-
338
- const DBObjectIncoming = z.object({
339
- '@_table': z.literal('sys_db_object'),
340
- sys_db_object: z.record(z.any()),
341
- })
342
-
343
- const SysDocumentation = z.object({
344
- sys_documentation: z.object({
345
- element: TextStringSchema.optional(),
346
- label: TextStringSchema.optional(),
347
- language: TextStringSchema.optional(),
348
- hint: TextStringSchema.optional(),
349
- help: TextStringSchema.optional(),
350
- name: TextStringSchema.optional(),
351
- plural: TextStringSchema.optional(),
352
- sys_id: TextStringSchema.optional(),
353
- url: TextStringSchema.optional(),
354
- url_target: TextStringSchema.optional(),
355
- }),
356
- })
357
-
358
- const LicensingConfig = z.object({
359
- ua_table_licensing_config: z.object({
360
- name: TextStringSchema.optional(),
361
- op_insert: TextBooleanSchema.optional(),
362
- op_update: TextBooleanSchema.optional(),
363
- op_delete: TextBooleanSchema.optional(),
364
- is_fulfillment: TextBooleanSchema.optional(),
365
- license_model: TextStringSchema.optional(),
366
- owner_condition: TextStringSchema.optional(),
367
- license_condition: TextStringSchema.optional(),
368
- license_roles: TextStringSchema.optional(),
369
- }),
370
- })
371
-
372
- // Attributes from element=table in bootstrap.xml
373
- const TableSchemaBootstrapAttributes = z
374
- .object({
375
- '@_name': z.string(),
376
- '@_extends': z.string().optional(),
377
- '@_label': z.string().optional(),
378
- '@_max_length': z.any().optional(),
379
-
380
- // From sys_dictionary/sys_db_object
381
- '@_audit': BooleanFromString,
382
- '@_read_only': BooleanFromString,
383
- '@_text_index': BooleanFromString,
384
- '@_client_scripts_access': BooleanFromString,
385
- '@_ws_access': BooleanFromString,
386
- '@_alter_access': BooleanFromString,
387
- '@_create_access': BooleanFromString,
388
- '@_delete_access': BooleanFromString,
389
- '@_update_access': BooleanFromString,
390
- '@_query_access': BooleanFromString,
391
- '@_actions_access': BooleanFromString,
392
- '@_read_access': BooleanFromString,
393
- '@_is_extendable': BooleanFromString,
394
- '@_caller_access': IntFromString,
395
- '@_scriptable_table': BooleanFromString,
396
-
397
- '@_attributes': z
398
- .string()
399
- .transform((values) => {
400
- const ret = {}
401
- if (values === '') {
402
- return undefined
403
- }
404
- const entries = values.split(',')
405
- entries.forEach((attr) => {
406
- const s = attr.split('=')
407
- if (s.length === 2 && s[0] && s[1]) {
408
- try {
409
- ret[s[0]] = JSON.parse(s[1])
410
- } catch (err) {
411
- ret[s[0]] = s[1]
412
- }
413
- }
414
- })
415
- return ret
416
- })
417
- .optional(),
418
- })
419
- .catchall(z.any())
420
-
421
- const DictionaryXmlSchema = z.object({
422
- sys_dictionary: z
423
- .object({
424
- '@_action': z.union([z.literal('INSERT_OR_UPDATE'), z.literal('DELETE'), z.literal('delete_multiple')]),
425
- sys_id: z
426
- .object({
427
- '#text': z.string().min(32).max(32).or(z.number()),
428
- })
429
- .transform((val) => val['#text'])
430
- .optional(),
431
- '@_element': z.string(),
432
- '@_table': z.string(),
433
- })
434
- .catchall(
435
- z
436
- .object({
437
- '#text': z.union([z.string(), z.boolean(), z.number(), z.undefined()]),
438
- })
439
- .transform((val) => val['#text'])
440
- ),
441
- })
442
-
443
- const IndexSchemaBootstrapAttributes = z.object({
444
- '@_name': z.string(),
445
- '@_unique': BooleanFromString,
446
- element: z.object({ '@_name': z.string() }).or(
447
- z.array(
448
- z.object({
449
- '@_name': z.string(),
450
- })
451
- )
452
- ),
453
- })
454
-
455
- const ColumnSchemaBootstrapAttributes = TableSchemaBootstrapAttributes.omit({ '@_extends': true })
456
- .extend({
457
- '@_choice': z.coerce.number().optional(),
458
- '@_active': BooleanFromString,
459
- '@_mandatory': BooleanFromString,
460
- '@_display': BooleanFromString,
461
- '@_type': z.string().optional(),
462
- '@_use_dependent_field': BooleanFromString,
463
- '@_use_dynamic_default': BooleanFromString,
464
- '@_reference': z.string().optional(),
465
- '@_virtual': BooleanFromString,
466
- '@_default': z.string().optional(),
467
- '@_calculation': z.string().optional(),
468
- '@_choice_field': z.string().optional(),
469
- '@_function_definition': z.string().optional(),
470
- '@_reference_floats': BooleanFromString,
471
- '@_reference_key': z.string().optional(),
472
- '@_dynamic_creation_script': z.string().optional(),
473
- '@_dynamic_creation': BooleanFromString,
474
- '@_plural': z.string().optional(),
475
- '@_hint': z.string().optional(),
476
- '@_help': z.string().optional(),
477
- '@_widget': z.string().optional(),
478
- '@_table_reference': BooleanFromString,
479
- '@_element_reference': BooleanFromString,
480
- '@_unique': BooleanFromString,
481
- '@_spell_check': BooleanFromString,
482
- '@_xml_view': BooleanFromString,
483
- '@_array': BooleanFromString,
484
- '@_text_index': BooleanFromString,
485
- '@_primary': BooleanFromString,
486
- '@_reference_qual': z.string().optional(),
487
- choice: z.object({ element: z.array(z.any()).or(z.record(z.any())).optional() }).optional(),
488
- '@_attributes': z
489
- .string()
490
- .transform((values) => {
491
- const ret = {}
492
- if (values === '') {
493
- return undefined
494
- }
495
- const entries = values.split(',')
496
- entries.forEach((attr) => {
497
- const s = attr.split('=')
498
- if (s.length === 2 && s[0] && s[1]) {
499
- try {
500
- ret[s[0]] = JSON.parse(s[1])
501
- } catch (err) {
502
- ret[s[0]] = s[1]
503
- }
504
- }
505
- })
506
- return ret
507
- })
508
- .optional(),
509
- })
510
- .catchall(z.any())
511
-
512
- const ChoiceSchema = z.object({
513
- label: z.string().optional(),
514
- value: z.string().optional(),
515
- sequence: z.coerce.number().optional(),
516
- dependent_value: z.coerce.number().or(z.string()).optional(),
517
- hint: z.string().optional(),
518
- inactive: BooleanFromString.default(false).optional(),
519
- inactive_on_update: BooleanFromString.default(false).optional(),
520
- language: z.string().optional(),
521
- })
522
-
523
- const ChoiceSchemaIncoming = ChoiceSchema.omit({ value: true })
524
-
525
- function composeLicenseConfig(tableName: string, config, node) {
526
- return {
527
- kind: 'ua_table_licensing_config',
528
- guid: `${tableName}_license`,
529
- data: {
530
- table: 'ua_table_licensing_config',
531
- $id: tableName,
532
- data: {
533
- name: tableName,
534
- op_insert: config.op_insert ?? true,
535
- op_update: config.op_update ?? true,
536
- op_delete: config.op_delete ?? true,
537
- is_fulfillment: config.is_fulfillment ?? false,
538
- license_model: config.license_model ?? 'none',
539
- owner_condition: config.owner_condition ?? '',
540
- license_condition: config.license_condition ?? '',
541
- license_roles: config.license_roles ? config.license_roles.join(',') : '',
542
- },
543
- },
544
- node,
545
- }
546
- }
547
-
548
- type ComposedTableData = {
549
- data: {
550
- bootstrapData: any
551
- dbObjectData: any
552
- }
553
- }
554
-
555
- const tableNameRegex = new RegExp(`^[a-z_][a-z0-9_]*[a-z0-9]$`)
556
-
557
- export default Plugin({
558
- name: 'Table',
559
- ownedTables: {
560
- sys_db_object: { diagnosticLevel: Diagnostic.Level.Warn },
561
- },
562
- extractors: {
563
- entity: {
564
- fluent: {
565
- // TODO: Cast to `any` is temporary workaround for the circular nature of Table entities
566
- CallExpression: (node, context) => {
567
- const result = extractCallExpression(Table, 'table', node, context, (table) => table.name)
568
- if (!result.handled || !result.data) {
569
- return result
570
- }
571
-
572
- const data = result.data
573
- const diagnostics = result.diagnostics
574
- const scopeName = context.app.config.scope
575
- const scopeRegex = new RegExp(`^${scopeName}_`)
576
- const columnNameRegex = new RegExp(`^[a-z_][a-z0-9_]*$`)
577
- const tableName = data.getProperty('name')
578
- const scopeMatches = tableName.getValue().match(scopeRegex)
579
- let ignoreColumnNameCheck = false
580
-
581
- if (!tableName.getValue().match(tableNameRegex)) {
582
- diagnostics.push(
583
- new FluentDiagnostic(
584
- tableName.getNode(),
585
- `Table name must only contain lowercase letters, numbers, and underscores and end with a letter or number`
586
- )
587
- )
588
- }
589
-
590
- if (!scopeMatches) {
591
- const nameNode = tableName.getNode().asKindOrThrow(ts.SyntaxKind.StringLiteral)
592
- if (nameNode.getParent().getKindName() !== 'AsExpression') {
593
- diagnostics.push(
594
- new FluentDiagnostic(
595
- tableName.getNode(),
596
- `'name' property must start with scope prefix '${scopeName}'`
597
- )
598
- )
599
- } else {
600
- ignoreColumnNameCheck = true
601
- }
602
- }
603
-
604
- const schema = data.getProperty('schema')
605
- const schemaNode = schema.getNode().asKindOrThrow(ts.SyntaxKind.ObjectLiteralExpression)
606
- for (const columnName in schema.getValue()) {
607
- const columnNode = schemaNode.getPropertyOrThrow(columnName)
608
- if (
609
- !ignoreColumnNameCheck &&
610
- !scopeMatches &&
611
- !isSNScope(scopeName) &&
612
- !columnName.match(scopeRegex)
613
- ) {
614
- diagnostics.push(
615
- new FluentDiagnostic(
616
- columnNode,
617
- `Column name must be prefixed with scope '${scopeName}' if table name does not contain prefix`
618
- )
619
- )
620
- }
621
-
622
- if (!columnName.match(columnNameRegex)) {
623
- diagnostics.push(
624
- new FluentDiagnostic(
625
- columnNode,
626
- `Column name must only contain lowercase letters, numbers, and underscores`
627
- )
628
- )
629
- }
630
- }
631
-
632
- const declaration = node.getParentIfKind(ts.SyntaxKind.VariableDeclaration)
633
- if (
634
- !declaration ||
635
- !declaration.isExported() ||
636
- !declaration.isNamedExport() ||
637
- declaration.getName() !== tableName.getValue()
638
- ) {
639
- diagnostics.push(
640
- new FluentDiagnostic(
641
- node,
642
- `Table definition should be exported as a named export with the name '${tableName.getValue()}'`,
643
- { level: Diagnostic.Level.Warn }
644
- )
645
- )
646
- }
647
-
648
- diagnostics.push(...getLabelDiagnostics(data))
649
- const entityData = new EntityData(
650
- 'table',
651
- tableName.getValue(),
652
- new ObjectData(data.getProperties(), data.getNode()),
653
- data.getNode(),
654
- data.getInstallMethod(),
655
- [tableName.getValue()]
656
- )
657
- return { handled: true, data: entityData, diagnostics }
658
- },
659
- },
660
- },
661
- xml(xml, context) {
662
- const bootstrapData = {}
663
- let dbObjectData = {}
664
- const bootstrapDatabaseXML = BootstrapDatabaseElement.safeParse(xml.data['database'])
665
- if (bootstrapDatabaseXML.success) {
666
- const data = TableSchemaBootstrapAttributes.parse(bootstrapDatabaseXML.data.element)
667
- Object.entries(data).forEach(([key, value]) => {
668
- if (key.startsWith('@_')) {
669
- bootstrapData[key.substring(2)] = value
670
- } else if (key === 'element') {
671
- //
672
- } else {
673
- bootstrapData[key] = value
674
- }
675
- })
676
- context.updateHandledXMLs(xml.filePath, 'handled')
677
- }
678
-
679
- const db_object_inc = DBObjectIncoming.safeParse(xml.data['record_update'])
680
- if (db_object_inc.success) {
681
- dbObjectData = DBObjectIncomingAttributes.parse(db_object_inc.data.sys_db_object)
682
- context.updateHandledXMLs(xml.filePath, 'handled')
683
- return new XmlData(
684
- dbObjectData,
685
- xml.filePath,
686
- 'sys_db_object',
687
- db_object_inc.data.sys_db_object['@_action']
688
- )
689
- } else if (!bootstrapDatabaseXML.success) {
690
- const record_update = xml.data['record_update']
691
- if (record_update) {
692
- const table = Object.keys(record_update)[0]
693
- if (!table || !componentTables.includes(table)) {
694
- return
695
- }
696
-
697
- if (table === 'sys_documentation') {
698
- const data = SysDocumentation.parse(record_update[table]).sys_documentation
699
- return new XmlData(
700
- {
701
- table: table,
702
- id: record_update[table][table]['sys_id']?.['#text'] ?? GUID(),
703
- data,
704
- },
705
- xml.filePath,
706
- 'sys_documentation',
707
- record_update[table]['@_action']
708
- )
709
- }
710
-
711
- if (table === 'ua_table_licensing_config') {
712
- const data = LicensingConfig.parse(record_update).ua_table_licensing_config
713
- return new XmlData(
714
- {
715
- table: table,
716
- id: record_update[table]['sys_id']?.['#text'] ?? GUID(),
717
- data,
718
- },
719
- xml.filePath,
720
- 'ua_table_licensing_config',
721
- record_update[table]['@_action']
722
- )
723
- }
724
-
725
- const data = DictionaryXmlSchema.safeParse(record_update)
726
- if (data.success) {
727
- const {
728
- '@_action': action,
729
- '@_element': element,
730
- '@_table': dictTable,
731
- sys_id,
732
- ...dict
733
- } = data.data.sys_dictionary
734
- return new XmlData(
735
- {
736
- table: table,
737
- id: sys_id ?? `${dict['name']}_${dict['element'] !== '' ? dict['element'] : '_null'}`,
738
- data: dict,
739
- },
740
- xml.filePath,
741
- 'sys_dictionary',
742
- action
743
- )
744
- }
745
- context.updateHandledXMLs(xml.filePath, 'ignored')
746
- return
747
- }
748
- }
749
-
750
- // Columns and Indexes
751
- const columns: z.infer<typeof ColumnSchemaBootstrapAttributes>[] = []
752
- const idxElements: IndexType[] = []
753
- if (bootstrapDatabaseXML.success && bootstrapDatabaseXML.data.element['element']) {
754
- const element = bootstrapDatabaseXML.data.element['element']
755
- const elementsArray = isArray(element) ? element : [element]
756
- columns.push(...z.array(ColumnSchemaBootstrapAttributes).parse(elementsArray))
757
-
758
- columns.forEach((element) => {
759
- if (element.choice && !isEmpty(element.choice)) {
760
- element['choice_elements'] = {}
761
- const choices = isArray(element.choice.element)
762
- ? element.choice.element
763
- : [element.choice.element]
764
- choices.forEach((choice) => {
765
- const obj = removeAttributeTag(choice)
766
- const choiceData = ChoiceSchemaIncoming.parse(obj)
767
- if (!choiceData.label) {
768
- choiceData.label = obj.value
769
- }
770
- element['choice_elements'][obj.value] = choiceData
771
- })
772
- }
773
-
774
- element = removeAttributeTag(element)
775
- })
776
- bootstrapData['columns'] = columns.reduce((map, obj) => ((map[obj['name']] = obj), map), {})
777
-
778
- let elements = bootstrapDatabaseXML.data.element['index']
779
- elements = isArray(elements) ? elements : [elements]
780
- elements.forEach((element) => {
781
- const idxData = IndexSchemaBootstrapAttributes.safeParse(element)
782
- if (idxData.success) {
783
- idxElements.push({
784
- name: idxData.data['@_name'],
785
- element: isArray(idxData.data.element)
786
- ? idxData.data.element.reduce((arr, curr) => {
787
- arr.push(curr['@_name'])
788
- return arr
789
- }, [] as string[])
790
- : idxData.data.element['@_name'],
791
- unique: idxData.data['@_unique'] ?? false,
792
- })
793
- }
794
- })
795
- bootstrapData['index'] = idxElements
796
- }
797
-
798
- return new XmlData(bootstrapData, xml.filePath, 'bootstrap')
799
- },
800
- },
801
- composers: {
802
- entity: {
803
- async table(entity, context) {
804
- const node = entity.getNode()
805
- const data = entity.getValue()
806
- const table = TableSchemaFull.parse(data)
807
-
808
- const composeData = compose(table)
809
- const { columnData, documentation } = composeColumns(
810
- table.schema as Record<string, ColumnSchema>,
811
- context,
812
- table.name,
813
- table.display
814
- )
815
-
816
- composeData['columns'] = columnData
817
-
818
- const entities: LinkedDocument[] = []
819
- if (table.auto_number) {
820
- const data = table.auto_number
821
-
822
- const numberRecord = SysNumber(table.name, data.number_of_digits, data.number, data.prefix)
823
-
824
- const composedNumber = await RecordPlugin.composers.entity.record(
825
- new EntityData(
826
- 'record',
827
- context.registerExplicitId(numberRecord.table, numberRecord.$id),
828
- ObjectData.fromObjectValue(numberRecord, node),
829
- node
830
- ),
831
- context
832
- )
833
-
834
- entities.push(composedNumber)
835
-
836
- composeData['number_ref'] = composedNumber.guid
837
- }
838
-
839
- documentation.forEach((doc) => {
840
- entities.push({
841
- kind: 'sys_documentation',
842
- node: node,
843
- data: doc,
844
- guid: doc.$id as string,
845
- })
846
- })
847
-
848
- const docs = composeDocumentation('', table.name, table.label)
849
- docs.forEach((doc) => {
850
- entities.push({
851
- kind: 'sys_documentation',
852
- node: node,
853
- data: doc,
854
- guid: doc.$id as string,
855
- })
856
- })
857
-
858
- composeData['index'] = table.index
859
-
860
- if (table.licensing_config) {
861
- entities.push(composeLicenseConfig(composeData.name, table.licensing_config, node))
862
- }
863
-
864
- entities.push({
865
- kind: 'bootstrap',
866
- node,
867
- guid: composeData.name,
868
- data: { data: { bootstrapData: composeData, dbObjectData: composeData } },
869
- })
870
-
871
- return entities
872
- },
873
- },
874
- xml: {
875
- bootstrap(xml) {
876
- return {
877
- kind: xml.kind,
878
- guid: xml.data['name'] as string,
879
- data: { data: { bootstrapData: xml.data } },
880
- }
881
- },
882
- sys_db_object(xml) {
883
- return {
884
- kind: 'bootstrap',
885
- guid: `${xml.data['name']}`,
886
- data: { data: { dbObjectData: xml.data } },
887
- action: xml.action,
888
- }
889
- },
890
- sys_dictionary(xml) {
891
- const data = xml.data['data']!
892
- return {
893
- kind: 'sys_dictionary',
894
- guid:
895
- (xml.data['id'] as string) ??
896
- `${data['name']}_${data['element'] !== '' ? data['element'] : '_null'}`,
897
- data: xml.data,
898
- action: xml.action,
899
- }
900
- },
901
- },
902
- },
903
- arrangers: {
904
- bootstrap(_document: Document<any>) {
905
- return { handled: false }
906
- },
907
- sys_dictionary(document: Document<any>) {
908
- if ((document.data as any).table !== 'sys_dictionary') {
909
- return { handled: false }
910
- }
911
- const tableName = (document.data as any).data.name
912
- return {
913
- handled: true,
914
- result: tableName ? { kind: 'bootstrap', guid: tableName } : undefined,
915
- }
916
- },
917
- },
918
- generators: {
919
- bootstrap(document, context) {
920
- const parsedBoostrapData = TableSchemaBootstrapIncoming.safeParse(
921
- (document.data as ComposedTableData).data.bootstrapData
922
- )
923
- if (!parsedBoostrapData.success) {
924
- return undefined
925
- }
926
-
927
- return linkDocument(
928
- document,
929
- generateNamedCallExpressionExportForDocument(
930
- context,
931
- {
932
- sourceFile: getOrCreateEntitySourceFile(context, parsedBoostrapData.data.name),
933
- moduleSpecifier: '@servicenow/sdk/core',
934
- exportName: parsedBoostrapData.data.name,
935
- },
936
- Table,
937
- {}
938
- ).getInitializerIfKindOrThrow(ts.SyntaxKind.CallExpression)
939
- )
940
- },
941
- sys_dictionary(document, context: Context, linkedDocuments) {
942
- const data = (document.data as any).data
943
- const updateName = data.sys_update_name
944
- const table = linkedDocuments.find((doc) => doc.guid === data.name)
945
- return table && table.node
946
- ? { ...document, node: table.node }
947
- : linkDocument(
948
- document,
949
- generateCallExpressionExportForDocument(
950
- context,
951
- {
952
- sourceFile: getOrCreateEntitySourceFile(
953
- context,
954
- updateName ?? `sys_dictionary_${document.guid}`
955
- ),
956
- moduleSpecifier: '@servicenow/sdk/core',
957
- },
958
- NowRecord,
959
- { $id: document.guid }
960
- ).getExpressionIfKindOrThrow(ts.SyntaxKind.CallExpression)
961
- )
962
- },
963
- record(document, context) {
964
- if (
965
- document.data?.['table'] !== 'sys_documentation' &&
966
- document.data?.['table'] !== 'ua_table_licensing_config'
967
- ) {
968
- return
969
- }
970
-
971
- return linkDocument(
972
- document,
973
- generateCallExpression(
974
- context,
975
- getOrCreateEntitySourceFile(context, `${document.data?.['data'].name}`),
976
- '@servicenow/sdk/core',
977
- NowRecord,
978
- { $id: document.guid }
979
- )
980
- )
981
- },
982
- },
983
- serializers: {
984
- bootstrap(document) {
985
- const composedData = (document.data as ComposedTableData).data
986
- const { columns, index, attributes, ...bootstrapData } = composedData.bootstrapData
987
-
988
- if (bootstrapData.live_feed) {
989
- // live_feed needs to be a table sys_dictionary attribute so it can be synced to sys_db_object by a startup process
990
- attributes['live_feed'] = true
991
- }
992
-
993
- const root = create({ version: '1.0' }).ele('database')
994
- const composedAttributes = composeAttributes(attributes)
995
- const collection = root.ele('element', { ...bootstrapData, attributes: composedAttributes }!)
996
- for (const column of Object.values(columns)) {
997
- const { choice_elements, attributes, ...parsedColumn } = column as ColumnSchema
998
- const columnAttributes = composeAttributes(attributes)
999
- const element = collection.ele('element', { ...parsedColumn, attributes: columnAttributes }!)
1000
-
1001
- buildChoices(column as ColumnSchema, element)
1002
- }
1003
-
1004
- buildIndexes(index, collection)
1005
-
1006
- return {
1007
- name: `${bootstrapData.name}.xml`,
1008
- directory: 'dictionary',
1009
- content: root.end({ prettyPrint: true }),
1010
- usedIds: [],
1011
- }
1012
- },
1013
- sys_dictionary(_document) {
1014
- // Don't serialize
1015
- return undefined
1016
- },
1017
- },
1018
- transformers: {
1019
- bootstrap: {
1020
- CallExpression(document, context) {
1021
- return transformTable(document, context)
1022
- },
1023
- },
1024
- sys_dictionary: {
1025
- CallExpression(document, context: Context) {
1026
- if (getCallExpressionName(document.node as ts.CallExpression) !== Table.name) {
1027
- return RecordPlugin.transformers!.record!.CallExpression(document, context)
1028
- }
1029
-
1030
- context.logger.info(
1031
- `Deferring handling of sys_dictionary '${document.guid}' values to values in bootstrap.xml '${document.parent!.guid}'`
1032
- )
1033
- return true
1034
- },
1035
- },
1036
- },
1037
- postProcessors: {
1038
- entities(entities, context) {
1039
- const { interfaces, properties, imports, namedImports } = {
1040
- interfaces: [] as ts.OptionalKind<ts.InterfaceDeclarationStructure>[],
1041
- properties: [] as ts.OptionalKind<ts.PropertySignatureStructure>[],
1042
- imports: {} as Record<string, ts.OptionalKind<ts.ImportDeclarationStructure>>,
1043
- namedImports: [] as (ts.OptionalKind<ts.ImportSpecifierStructure> & {
1044
- existingImport: ts.ImportDeclaration
1045
- })[],
1046
- }
1047
- const generatedTableFile: ts.SourceFile | undefined = context.compiler.getGeneratedTableFile()
1048
- entities
1049
- .filter((entity) => entity.getKind() === 'table')
1050
- .forEach((table) => {
1051
- const tableName = table.getProperty('name')!.getValue() as string
1052
- const extendsTable = table.getProperty('extends')?.getValue() as string
1053
- if (tableName && tableName.trim().length > 0 && tableName.match(tableNameRegex)) {
1054
- if (!context.compiler.interfaceExistsInGlobalDeclaration(tableName)) {
1055
- interfaces.push({
1056
- name: tableName,
1057
- extends: [`Helper<typeof ${tableName}>`],
1058
- })
1059
- }
1060
- if (!context.compiler.propertyExistsInGlobalDeclaration(tableName)) {
1061
- let interfaceType = `Table<TableSchemas.${tableName}>`
1062
- if (extendsTable) {
1063
- interfaceType = `Table<TableSchemas.${tableName}, "${extendsTable}">`
1064
- }
1065
- properties.push({
1066
- name: tableName,
1067
- type: interfaceType,
1068
- })
1069
- }
1070
-
1071
- const filePath = table.getNode().getSourceFile().getFilePath()
1072
- const resolvedModuleSpecifier = generatedTableFile?.getRelativePathAsModuleSpecifierTo(
1073
- filePath
1074
- ) as string
1075
- const importExists = context.compiler.importExistsInGlobalDeclaration(resolvedModuleSpecifier)
1076
-
1077
- if (!importExists) {
1078
- if (imports[filePath]) {
1079
- ;(imports[filePath].namedImports! as string[]).push(tableName)
1080
- } else {
1081
- imports[filePath] = {
1082
- namedImports: [tableName],
1083
- moduleSpecifier: resolvedModuleSpecifier,
1084
- }
1085
- }
1086
- } else {
1087
- const namedImportExists = importExists
1088
- ?.getNamedImports()
1089
- .find((value) => value.getName() === tableName)
1090
- if (!namedImportExists) {
1091
- namedImports.push({
1092
- existingImport: importExists,
1093
- name: tableName,
1094
- })
1095
- }
1096
- }
1097
- }
1098
- })
1099
- context.compiler.addTableInterfacesToGlobalDeclaration({
1100
- interfaces,
1101
- properties,
1102
- imports,
1103
- namedImports,
1104
- })
1105
- },
1106
- },
1107
- })
1108
-
1109
- function transformTable(document, context) {
1110
- const expressionName = getCallExpressionName(document.node)
1111
- if (expressionName !== Table.name) {
1112
- return false
1113
- }
1114
- const [args] = document.node.getArguments()
1115
- if (!ts.Node.isObjectLiteralExpression(args)) {
1116
- return false
1117
- }
1118
-
1119
- if (document.action === 'DELETE') {
1120
- removeNode(document.node)
1121
- return true
1122
- }
1123
-
1124
- if (!document.changedData) {
1125
- return true
1126
- }
1127
-
1128
- const composedData = (document.changedData as ComposedTableData).data
1129
- const xmlData = (document.xmlData as ComposedTableData).data
1130
-
1131
- let bootstrap_data = {}
1132
- let db_data = {}
1133
- if (!isEmpty(composedData.bootstrapData)) {
1134
- // sys_db_object or node without bootstrap.xml. Mark as handled and ignore
1135
- bootstrap_data = TableSchemaBootstrapIncoming.partial().parse(composedData.bootstrapData)
1136
- }
1137
- if (!isEmpty(composedData.dbObjectData)) {
1138
- db_data = DBObjectIncomingAttributes.partial().parse(composedData.dbObjectData)
1139
- }
1140
-
1141
- const { auto_number, number_ref, extends: ext, index, columns, ...bootstrap_rest } = mapNames(bootstrap_data)
1142
- const { create_access, delete_access, update_access, read_access, caller_access, ...db_rest } = mapNames(db_data)
1143
- const rest = { ...bootstrap_rest, ...db_rest }
1144
-
1145
- if (ext) {
1146
- rest['extends'] = ext
1147
- }
1148
-
1149
- if (caller_access) {
1150
- rest['caller_access'] = callerAccess[caller_access]
1151
- }
1152
-
1153
- if (!isEmpty(db_data)) {
1154
- rest.actions = getActionsArray(xmlData.dbObjectData)
1155
- }
1156
-
1157
- if (!rest.attributes) {
1158
- delete rest.attributes
1159
- }
1160
-
1161
- transformFunctionArguments(document.node, Table as any, rest)
1162
-
1163
- // Handle columns
1164
- const incomingColumns = xmlData.bootstrapData ? xmlData.bootstrapData.columns : undefined
1165
-
1166
- updateDisplayValue(document.node, columns, incomingColumns)
1167
- transformColumns(columns, incomingColumns, args, context)
1168
- transformIndexes(xmlData, args)
1169
- return true
1170
- }
1171
-
1172
- function transformIndexes(xmlData, args) {
1173
- if (xmlData.bootstrapData?.index?.length > 0) {
1174
- // find the correct object literal
1175
- const indexProp = getPropertyAssignment(args, 'index')
1176
- if (indexProp) {
1177
- mergeDataIntoObjectLiteralArray(
1178
- indexProp.getFirstChildByKindOrThrow(ts.SyntaxKind.ArrayLiteralExpression),
1179
- Object.values(xmlData.bootstrapData?.index),
1180
- 'name'
1181
- )
1182
- } else {
1183
- const newIndexProp = getOrCreatePropertyAssignment(args, 'index', '[]')
1184
- newIndexProp.setInitializer(stringify(xmlData.bootstrapData.index))
1185
- }
1186
- } else if (xmlData.bootstrapData) {
1187
- const indexProp = getPropertyAssignment(args, 'index')
1188
- if (indexProp) {
1189
- indexProp.remove()
1190
- }
1191
- }
1192
- }
1193
-
1194
- function composeAttributes(attributes: Record<string, any> | undefined) {
1195
- if (!attributes) {
1196
- return ''
1197
- }
1198
-
1199
- return Object.entries(attributes)
1200
- .map(([key, value]) => `${key}=${value}`)
1201
- .join(',')
1202
- }
1203
-
1204
- function updateDisplayValue(node: ts.CallExpression, columns: ColumnSchema, incomingColumns: ColumnSchema) {
1205
- const display = Object.values(columns ?? {}).filter((col: any) => col.display)
1206
- if (display) {
1207
- const displayName = Object.values(incomingColumns ?? {}).find((c) => c.display)
1208
- if (displayName) {
1209
- transformFunctionArguments(node, Table as any, { display: displayName.name })
1210
- }
1211
- }
1212
- }
1213
-
1214
- function composeDocumentation(columnName: string, tableName: string, labels?: string | Documentation[]): NowRecord[] {
1215
- const labelData: NowRecord[] = []
1216
-
1217
- if (!labels || !isArray(labels)) {
1218
- return labelData
1219
- }
1220
-
1221
- labels.forEach((label) => {
1222
- const labelValue = label.label ?? columnName !== '' ? columnName : tableName
1223
- labelData.push(
1224
- NowRecord({
1225
- table: 'sys_documentation',
1226
- $id: `${tableName}_${columnName ? columnName + '_' : ''}${label.language}`,
1227
- data: { label: labelValue, element: columnName, name: tableName, ...label },
1228
- })
1229
- )
1230
- })
1231
- return labelData
1232
- }
1233
-
1234
- function getLabel(label?: string | Documentation[]): string | undefined {
1235
- if (!label || isArray(label)) {
1236
- // use column name if no label specified
1237
- return
1238
- }
1239
-
1240
- // label is an explicit string value
1241
- return label
1242
- }
1243
-
1244
- export function getDefaultMaxLength(column: ColumnSchema): number {
1245
- switch (column.entityKind) {
1246
- case 'conditions':
1247
- case 'glide_list':
1248
- return 4000
1249
- case 'decimal':
1250
- return 20
1251
- case 'domain_id':
1252
- case 'document_id':
1253
- case 'reference':
1254
- return 32
1255
- case 'domain_path':
1256
- case 'user_roles':
1257
- return 255
1258
- case 'script':
1259
- return 8000
1260
- case 'table_name':
1261
- case 'field_name':
1262
- return 80
1263
- default:
1264
- /**
1265
- * For types mentioned below it default to 40 on instance
1266
- * boolean | integer | image | choice | radio | sys_class_name | translated_field | translated_text | version | glide_date | glide_date_time | calendar_date_time
1267
- * datetime | due_date | integer_date | schedule_date_time | date | generic
1268
- *
1269
- * TODO::We need to request max_length from user for string column type because its mandatory on instance.
1270
- */
1271
- return 40
1272
- }
1273
- }
1274
-
1275
- function composeColumns(columns: Record<string, ColumnSchema>, _context: Context, tableName: string, display?: string) {
1276
- const composedColumns = {}
1277
- const documentation: NowRecord[] = []
1278
- for (const [columnName, columnData] of Object.entries(columns)) {
1279
- const { maxLength, ...rest } = columnData
1280
- const column = ColumnSchema.parse(rest)
1281
- const requiresDropdown = column.dynamic_value_definitions || column.choices
1282
- const element = {
1283
- name: columnName,
1284
- type: column.entityKind === 'generic' ? column.column_type : column.entityKind,
1285
- attributes: column.attributes ?? undefined,
1286
- reference: column.referenceTable,
1287
- reference_cascade_rule: column.referenceTable ? column.cascadeRule : undefined,
1288
- audit: column.audit,
1289
- label: getLabel(column.label) ?? columnName,
1290
- max_length: maxLength ?? getDefaultMaxLength(column),
1291
- mandatory: column.mandatory,
1292
- read_only: column.read_only,
1293
- choice: choiceDropdown.indexOf(column.dropdown ?? (requiresDropdown ? 'dropdown_with_none' : 'none')),
1294
- display: display ? display === columnName : false,
1295
-
1296
- // dynamic values
1297
- virtual: column.dynamic_value_definitions?.type === 'calculated_value' ? true : undefined,
1298
- calculation:
1299
- column.dynamic_value_definitions?.type === 'calculated_value'
1300
- ? ModuleFunctionData.getGlueCode(
1301
- column.dynamic_value_definitions!['calculated_value'],
1302
- (n) => `${n}(current)`
1303
- )
1304
- : undefined,
1305
- choice_table:
1306
- column.dynamic_value_definitions?.type === 'choices_from_other_table'
1307
- ? column.dynamic_value_definitions.table
1308
- : undefined,
1309
- choice_field:
1310
- column.dynamic_value_definitions?.type === 'choices_from_other_table'
1311
- ? column.dynamic_value_definitions.field
1312
- : undefined,
1313
-
1314
- use_dependent_field: column.dynamic_value_definitions?.type === 'dependent_field' || undefined,
1315
-
1316
- dependent:
1317
- column.dynamic_value_definitions?.type === 'dependent_field'
1318
- ? column.dynamic_value_definitions!['column_name']
1319
- : undefined,
1320
-
1321
- default: column.default,
1322
-
1323
- function_definition: column.function_definition,
1324
- function_field: column.function_definition ? true : false,
1325
-
1326
- plural: column.plural,
1327
- hint: column.hint,
1328
- help: column.help,
1329
- widget: column.widget,
1330
- table_reference: column.table_reference,
1331
- element_reference: column.element_reference,
1332
- reference_key: column.reference_key,
1333
- spell_check: column.spell_check,
1334
- xml_view: column.xml_view,
1335
- reference_floats: column.reference_floats,
1336
- dynamic_creation: column.dynamic_creation,
1337
- dynamic_creation_script: column.dynamic_creation_script,
1338
- array: column.array,
1339
- text_index: column.text_index,
1340
- primary: column.primary,
1341
- unique: column.unique,
1342
- reference_qual: column.reference_qual,
1343
- }
1344
-
1345
- documentation.push(...composeDocumentation(columnName, tableName, column.label))
1346
-
1347
- if (column.choices) {
1348
- Object.keys(column.choices).forEach((key) => {
1349
- if (isObject(column.choices![key])) {
1350
- column.choices![key] = { value: key, ...column.choices![key] }
1351
- } else {
1352
- column.choices![key] = { value: key, label: column.choices![key] }
1353
- }
1354
- })
1355
- element['choice_elements'] = z.record(ChoiceSchema).parse(column.choices)
1356
- }
1357
-
1358
- composedColumns[columnName] = element
1359
- }
1360
- return { columnData: composedColumns, documentation }
1361
- }
1362
-
1363
- function compose(bootstrapData: z.infer<typeof TableSchemaBootstrap>) {
1364
- if (bootstrapData.live_feed) {
1365
- bootstrapData.attributes = {
1366
- // live_feed needs to be a table sys_dictionary attribute so it can be synced to sys_db_object by a startup process
1367
- ...bootstrapData.attributes,
1368
- live_feed: true,
1369
- }
1370
- }
1371
-
1372
- const composedData = {
1373
- // Generic data
1374
- name: bootstrapData.name,
1375
- type: 'collection',
1376
- extends: bootstrapData.extends,
1377
- label: getLabel(bootstrapData.label) ?? bootstrapData.name,
1378
-
1379
- // Controls
1380
- is_extendable: bootstrapData.extensible,
1381
- text_index: bootstrapData.text_index,
1382
- read_only: bootstrapData.read_only,
1383
- audit: bootstrapData.audit,
1384
-
1385
- access: bootstrapData.accessible_from,
1386
- caller_access: callerAccess.indexOf(bootstrapData.caller_access ?? 'none'),
1387
-
1388
- read_access: bootstrapData.actions?.includes('read'),
1389
- update_access: bootstrapData.actions?.includes('update'),
1390
- create_access: bootstrapData.actions?.includes('create'),
1391
- delete_access: bootstrapData.actions?.includes('delete'),
1392
-
1393
- ws_access: bootstrapData.allow_web_service_access,
1394
- alter_access: bootstrapData.allow_new_fields,
1395
- actions_access: bootstrapData.allow_ui_actions,
1396
- client_scripts_access: bootstrapData.allow_client_scripts,
1397
-
1398
- scriptable_table: bootstrapData.scriptable_table,
1399
-
1400
- attributes: bootstrapData.attributes,
1401
- }
1402
-
1403
- return composedData
1404
- }
1405
-
1406
- // API properties that are different in the bootstrap/sys_db_object file
1407
- const property_name_mapping = {
1408
- client_scripts_access: 'allow_client_scripts',
1409
- alter_access: 'allow_new_fields',
1410
- actions_access: 'allow_ui_actions',
1411
- ws_access: 'allow_web_service_access',
1412
- is_extendable: 'extensible',
1413
- access: 'accessible_from',
1414
- live_feed_enabled: 'live_feed',
1415
- }
1416
-
1417
- function mapNames(schema: any) {
1418
- Object.keys(schema).forEach((key) => {
1419
- if (property_name_mapping[key]) {
1420
- schema[property_name_mapping[key]] = schema[key]
1421
- delete schema[key]
1422
- }
1423
- })
1424
- return schema
1425
- }
1426
-
1427
- function transformColumns(
1428
- columns: ColumnSchema,
1429
- incomingSchema: ColumnSchema,
1430
- args: ts.ObjectLiteralExpression,
1431
- context: Context
1432
- ) {
1433
- const schemaProperty = getOrCreatePropertyAssignment(args, 'schema', '{}')
1434
-
1435
- if (!incomingSchema) {
1436
- return
1437
- }
1438
-
1439
- const schemaLiteral = schemaProperty.getChildrenOfKind(ts.SyntaxKind.ObjectLiteralExpression)[0]
1440
- if (!schemaLiteral) {
1441
- return
1442
- }
1443
-
1444
- const existingColumns = {}
1445
- schemaLiteral.getProperties().forEach((property) => {
1446
- const propertyAssignment = property.asKindOrThrow(ts.SyntaxKind.PropertyAssignment)
1447
- const name = propertyAssignment.getFirstChildByKindOrThrow(ts.SyntaxKind.Identifier).getText()
1448
- const callExp = propertyAssignment.getFirstChildByKindOrThrow(ts.SyntaxKind.CallExpression)
1449
- const callExpType = callExp.getFirstChildByKindOrThrow(ts.SyntaxKind.Identifier).getText()
1450
- const objectLiteral = callExp.getFirstChildByKindOrThrow(ts.SyntaxKind.ObjectLiteralExpression)
1451
- existingColumns[name] = {
1452
- node: propertyAssignment,
1453
- type: callExpType,
1454
- objectLiteral,
1455
- }
1456
-
1457
- if (!incomingSchema[name]) {
1458
- // Full bootstrap.xml does not have this existing column so remove it
1459
- removeNode(propertyAssignment)
1460
- }
1461
- })
1462
-
1463
- if (!columns || isEmpty(columns)) {
1464
- return
1465
- }
1466
-
1467
- Object.keys(incomingSchema).forEach((key) => {
1468
- const partialData = columns[key]
1469
- if (!existingColumns[key]) {
1470
- // This column doesn't exist so let's make it
1471
- const callExpFromType = getCallExpressionFromType(partialData.type)
1472
- createNewColumn(schemaLiteral, callExpFromType.name, partialData, context)
1473
- } else {
1474
- const existingColumn = existingColumns[key]
1475
- if (partialData) {
1476
- if (partialData.type && existingColumn.type !== partialData.type) {
1477
- // Switching the column type so regenerate the CallExpression and add all incoming data
1478
- removeNode(existingColumn.node)
1479
- const callExpFromType = getCallExpressionFromType(partialData.type)
1480
- createNewColumn(schemaLiteral, callExpFromType.name, incomingSchema[key], context)
1481
- } else {
1482
- // Update the existing column with changed data only
1483
- const transformedColumnData = transformColumnData(partialData, existingColumn.type)
1484
- mergeDataIntoObjectLiteral(existingColumn.objectLiteral, {
1485
- ...transformedColumnData,
1486
- choices: partialData.choice_elements,
1487
- })
1488
- }
1489
- }
1490
- if (existingColumn.node && !existingColumn.node.wasForgotten()) {
1491
- removeChoicesIfNecessary(existingColumn, incomingSchema[key])
1492
- removeAttributesIfNecessary(existingColumn, incomingSchema[key])
1493
- }
1494
- }
1495
- })
1496
- }
1497
-
1498
- function removeChoicesIfNecessary(existingColumn: any, columnFromBootstrap: any) {
1499
- const existingProperties = existingColumn.objectLiteral
1500
- .getProperties()
1501
- .reduce((a, v) => ({ ...a, [getObjectPropertyAssignmentName(v)]: v }), {})
1502
-
1503
- if (!existingProperties['choices']) {
1504
- return
1505
- }
1506
-
1507
- if (!columnFromBootstrap['choice_elements']) {
1508
- removeNode(existingProperties['choices'])
1509
- return
1510
- }
1511
-
1512
- const choicesFromBootstrap = Object.keys(columnFromBootstrap['choice_elements'])
1513
- const existingChoices = existingProperties['choices']
1514
- .getFirstChildByKind(ts.SyntaxKind.ObjectLiteralExpression)
1515
- .getProperties()
1516
- .reduce((a, v) => {
1517
- return {
1518
- ...a,
1519
- [getObjectPropertyAssignmentName(v)]: v,
1520
- }
1521
- }, {})
1522
- Object.keys(existingChoices).forEach((choice) => {
1523
- if (!choicesFromBootstrap.includes(choice)) {
1524
- removeNode(existingChoices[choice])
1525
- }
1526
- })
1527
- }
1528
-
1529
- function removeAttributesIfNecessary(existingColumn: any, columnFromBootstrap: any) {
1530
- const existingProperties = existingColumn.objectLiteral
1531
- .getProperties()
1532
- .reduce((a, v) => ({ ...a, [getObjectPropertyAssignmentName(v)]: v }), {})
1533
-
1534
- if (!existingProperties['attributes']) {
1535
- return
1536
- }
1537
-
1538
- if (!columnFromBootstrap['attributes']) {
1539
- removeNode(existingProperties['attributes'])
1540
- return
1541
- }
1542
-
1543
- const existingAttributes = existingProperties['attributes']
1544
- .getFirstChildByKind(ts.SyntaxKind.ObjectLiteralExpression)
1545
- .getProperties()
1546
- .reduce((a, v) => ({ ...a, [getObjectPropertyAssignmentName(v)]: v }), {})
1547
- Object.keys(existingAttributes).forEach((attr) => {
1548
- if (!(attr in columnFromBootstrap['attributes'])) {
1549
- removeNode(existingAttributes[attr])
1550
- }
1551
- })
1552
- }
1553
-
1554
- function generateNamedCallExpressionExportForDocument<const A extends unknown[]>(
1555
- context: Context,
1556
- info: {
1557
- sourceFile: ts.SourceFile
1558
- moduleSpecifier: string
1559
- exportName: string
1560
- },
1561
- fn: (...args: A) => unknown,
1562
- ...args: PartialElements<A>
1563
- ) {
1564
- const { sourceFile, moduleSpecifier } = info
1565
- return generateCallExpressionExport(context, sourceFile, moduleSpecifier, info.exportName, fn, ...args)
1566
- }
1567
-
1568
- function createNewColumn(schemaLiteral: ts.ObjectLiteralExpression, callExpName: string, data: any, context: Context) {
1569
- const propertyAssignment = schemaLiteral.addPropertyAssignment({
1570
- name: data.name,
1571
- initializer: `${callExpName}({})`,
1572
- })
1573
- const objectLiteral = propertyAssignment
1574
- .getInitializer()!
1575
- .getFirstChildByKindOrThrow(ts.SyntaxKind.ObjectLiteralExpression)
1576
- const transformedColumnData = transformColumnData(data, callExpName)
1577
- mergeDataIntoObjectLiteral(objectLiteral, { ...transformedColumnData, choices: data.choice_elements })
1578
- addNamedImportIfAbsent(context, schemaLiteral.getSourceFile(), '@servicenow/sdk/core', {
1579
- name: callExpName,
1580
- })
1581
- }
1582
-
1583
- type DB_ACTIONS = 'read' | 'delete' | 'create' | 'update'
1584
-
1585
- function getActionsArray(data) {
1586
- const actions: DB_ACTIONS[] = []
1587
- if (data.read_access) {
1588
- actions.push('read')
1589
- }
1590
- if (data.update_access) {
1591
- actions.push('update')
1592
- }
1593
- if (data.delete_access) {
1594
- actions.push('delete')
1595
- }
1596
- if (data.create_access) {
1597
- actions.push('create')
1598
- }
1599
-
1600
- return actions
1601
- }
1602
-
1603
- function buildIndexes(indexes: IndexType[] = [], collection: XMLBuilder) {
1604
- indexes.forEach((index) => {
1605
- const indexElement = collection.ele('index', { name: index.name, unique: index.unique })
1606
- if (isArray(index.element)) {
1607
- index.element.forEach((element) => {
1608
- indexElement.ele('element', { name: element })
1609
- })
1610
- } else {
1611
- indexElement.ele('element', { name: index.element })
1612
- }
1613
- })
1614
- }
1615
-
1616
- function buildChoices(column: ColumnSchema, element: XMLBuilder) {
1617
- if (!column.choice_elements) {
1618
- return
1619
- }
1620
-
1621
- const choices = element.ele('choice')
1622
- if (Array.isArray(column.choices) && column.choices.length > 0) {
1623
- // Formatted - choices: [1, 2, 3, 4]
1624
- for (const choice in column.choices) {
1625
- choices.ele('element', {
1626
- value: column.choices[choice],
1627
- label: column.choices[choice],
1628
- })
1629
- }
1630
- } else {
1631
- // Formatted - choices: { 1: { label: 'label' }, 2: { lable: label 2}, ...}
1632
- Object.entries(column.choice_elements).forEach((value) => {
1633
- if (isObject(value[1])) {
1634
- choices.ele('element', {
1635
- value: value[0],
1636
- ...(value[1] as ChoiceConfig),
1637
- })
1638
- } else {
1639
- choices.ele('element', {
1640
- value: value[1],
1641
- label: value[0],
1642
- })
1643
- }
1644
- })
1645
- }
1646
- }
1647
-
1648
- function transformColumnData(col: any, callExpFromType: string) {
1649
- const {
1650
- type: internal_type,
1651
- choice,
1652
- name,
1653
- virtual,
1654
- display,
1655
- choice_table,
1656
- choice_field,
1657
- use_dependent_field,
1658
- dependent,
1659
- calculation,
1660
- use_dynamic_default,
1661
- default_value,
1662
- choice_elements,
1663
- table,
1664
- default: def,
1665
- max_length,
1666
- reference,
1667
- reference_cascade_rule,
1668
- function_field,
1669
- reference_qual_condition,
1670
- ...column
1671
- } = col
1672
-
1673
- if (max_length !== undefined) {
1674
- column.maxLength = parseInt(max_length, 10)
1675
- }
1676
-
1677
- if (internal_type && callExpFromType === 'GenericColumn') {
1678
- column.column_type = internal_type
1679
- }
1680
-
1681
- if (choice !== undefined) {
1682
- column.dropdown = choiceDropdown[choice]
1683
- }
1684
-
1685
- if (reference) {
1686
- column.referenceTable = reference
1687
- }
1688
- if (reference_cascade_rule) {
1689
- column.cascadeRule = reference_cascade_rule
1690
- }
1691
-
1692
- // Handle dynamic values
1693
- if (calculation) {
1694
- column.dynamic_value_definitions = {
1695
- type: 'calculated_value',
1696
- calculated_value: calculation,
1697
- }
1698
- } else if (choice_table || choice_field) {
1699
- column.dynamic_value_definitions = {
1700
- type: 'choices_from_other_table',
1701
- table: choice_table,
1702
- field: choice_field,
1703
- }
1704
- } else if (dependent) {
1705
- column.dynamic_value_definitions = {
1706
- type: 'dependent_field',
1707
- column_name: dependent,
1708
- }
1709
- } else if (def) {
1710
- column.default = def
1711
- } else if (default_value) {
1712
- column.default = default_value
1713
- }
1714
-
1715
- if (column.label && column.label === name) {
1716
- delete column.label
1717
- }
1718
-
1719
- if (isEmpty(column.attributes)) {
1720
- delete column.attributes
1721
- } else if (isDefaultEdgeEncryptionAttribute(column.attributes)) {
1722
- delete column.attributes
1723
- }
1724
-
1725
- return column
1726
- }
1727
-
1728
- // The instance will sometimes add edge_encryption_enabled=true, this is a default so don't write it if it is the only one
1729
- function isDefaultEdgeEncryptionAttribute(attributes: any) {
1730
- return (
1731
- attributes &&
1732
- Object.entries(attributes).length === 1 &&
1733
- attributes.edge_encryption_enabled !== undefined &&
1734
- attributes.edge_encryption_enabled
1735
- )
1736
- }
1737
-
1738
- function removeAttributeTag(obj: any) {
1739
- Object.entries(obj).forEach(([key, value]) => {
1740
- if (key.startsWith('@_')) {
1741
- obj[key.substring(2)] = value
1742
- delete obj[key]
1743
- }
1744
- })
1745
- return obj
1746
- }
1747
-
1748
- function SysNumber(
1749
- category: TableName,
1750
- maximum_digits: number | undefined,
1751
- number?: number | undefined,
1752
- prefix?: string | undefined
1753
- ) {
1754
- return NowRecord({
1755
- table: 'sys_number',
1756
- $id: `${category as string}_${prefix}`,
1757
- data: {
1758
- category,
1759
- maximum_digits: maximum_digits ?? 1000,
1760
- number: number ?? 7,
1761
- prefix: prefix ?? 'PRE',
1762
- },
1763
- })
1764
- }
1765
-
1766
- export function generateColumnExpression<Type extends (...args: any) => any>(
1767
- expression: Type,
1768
- args: Parameters<Type>[0],
1769
- argsSetIfDefined?: Undefined<Parameters<Type>[0]>
1770
- ): tsc.CallExpression {
1771
- const setArgs = { ...args }
1772
- if (argsSetIfDefined) {
1773
- Object.keys(argsSetIfDefined).forEach((key) => {
1774
- if (argsSetIfDefined[key] !== undefined) {
1775
- setArgs[key] = argsSetIfDefined[key]
1776
- }
1777
- })
1778
- }
1779
-
1780
- return tsc.factory.createCallExpression(tsc.factory.createIdentifier(expression.name), undefined, [
1781
- createObjectExpression(setArgs),
1782
- ])
1783
- }
1784
-
1785
- export function createObjectExpression(firstArg: object): tsc.Expression {
1786
- return tsc.factory.createObjectLiteralExpression(
1787
- Object.entries(firstArg)
1788
- .filter(([_key, value]) => value !== undefined)
1789
- .map(([key, value]) => {
1790
- if (key === 'referenceTable') {
1791
- return tsc.factory.createPropertyAssignment(
1792
- tsc.factory.createIdentifier('referenceTable'),
1793
- tsc.factory.createStringLiteral(value)
1794
- )
1795
- } else if (key === 'calculated_value') {
1796
- return tsc.factory.createPropertyAssignment(
1797
- tsc.factory.createIdentifier(key),
1798
- tsc.factory.createTaggedTemplateExpression(
1799
- tsc.factory.createIdentifier('script'),
1800
- undefined,
1801
- tsc.factory.createNoSubstitutionTemplateLiteral(value, value)
1802
- )
1803
- )
1804
- } else if (key === 'maxLength') {
1805
- if (isNaN(+value)) {
1806
- return tsc.factory.createPropertyAssignment(
1807
- tsc.factory.createIdentifier(key),
1808
- tsc.factory.createAsExpression(
1809
- tsc.factory.createStringLiteral(value),
1810
- tsc.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)
1811
- )
1812
- )
1813
- }
1814
-
1815
- return tsc.factory.createPropertyAssignment(
1816
- tsc.factory.createIdentifier(key),
1817
- tsc.factory.createNumericLiteral(value)
1818
- )
1819
- }
1820
- return tsc.factory.createPropertyAssignment(
1821
- createPropertyIdentifier(key),
1822
- factoryCreateValue(value, tsc.factory)
1823
- )
1824
- })
1825
- )
1826
- }
1827
-
1828
- function factoryCreateValue(value: unknown, factory: tsc.NodeFactory) {
1829
- if (typeof value === 'string') {
1830
- return factory.createStringLiteral(value)
1831
- }
1832
-
1833
- if (typeof value === 'number') {
1834
- if (value >= 0) {
1835
- return factory.createNumericLiteral(value)
1836
- } else {
1837
- return factory.createPrefixUnaryExpression(
1838
- tsc.SyntaxKind.MinusToken,
1839
- factory.createNumericLiteral(Math.abs(value))
1840
- )
1841
- }
1842
- }
1843
-
1844
- if (typeof value === 'boolean') {
1845
- return value ? factory.createTrue() : factory.createFalse()
1846
- }
1847
-
1848
- if (typeof value === 'object') {
1849
- if (value === null) {
1850
- return factory.createNull()
1851
- }
1852
- if (isArray(value)) {
1853
- const newvals: tsc.Expression[] = []
1854
-
1855
- Object.values(value).forEach((v) => {
1856
- newvals.push(factoryCreateValue(v, factory))
1857
- })
1858
-
1859
- return factory.createArrayLiteralExpression(newvals)
1860
- } else if (ts.Structure.isImportSpecifier(value)) {
1861
- return factory.createIdentifier(value['name'])
1862
- } else {
1863
- return createObjectExpression(value)
1864
- }
1865
- }
1866
-
1867
- return factory.createNull()
1868
-
1869
- // throw new Error(`Unsupported value type: ${typeof value}`)
1870
- }
1871
-
1872
- type Undefined<T> = {
1873
- [P in keyof T]: T[P] | undefined
1874
- }
1875
- function getCallExpressionFromType(internal_type: string) {
1876
- switch (internal_type) {
1877
- case undefined:
1878
- case 'string':
1879
- return StringColumn
1880
- case 'boolean':
1881
- return BooleanColumn
1882
- case 'choice':
1883
- return ChoiceColumn
1884
- case 'conditions':
1885
- return ConditionsColumn
1886
- case 'date':
1887
- return OtherDateColumn
1888
- case 'calendar_date_time':
1889
- return CalendarDateTimeColumn
1890
- case 'datetime':
1891
- return BasicDateTimeColumn
1892
- case 'due_date':
1893
- return DueDateColumn
1894
- case 'glide_date':
1895
- return DateColumn
1896
- case 'glide_date_time':
1897
- return DateTimeColumn
1898
- case 'integer_date':
1899
- return IntegerDateColumn
1900
- case 'schedule_date_time':
1901
- return ScheduleDateTimeColumn
1902
- case 'decimal':
1903
- return DecimalColumn
1904
- case 'document_id':
1905
- return DocumentIdColumn
1906
- case 'domain_id':
1907
- return DomainIdColumn
1908
- case 'domain_path':
1909
- return DomainPathColumn
1910
- case 'field_name':
1911
- return FieldNameColumn
1912
- case 'integer':
1913
- return IntegerColumn
1914
- case 'radio':
1915
- return RadioColumn
1916
- case 'reference':
1917
- return ReferenceColumn
1918
- case 'script':
1919
- return ScriptColumn
1920
- case 'sys_class_name':
1921
- return SystemClassNameColumn
1922
- case 'table_name':
1923
- return TableNameColumn
1924
- case 'translated_field':
1925
- return TranslatedFieldColumn
1926
- case 'translated_text':
1927
- return TranslatedTextColumn
1928
- case 'user_roles':
1929
- return UserRolesColumn
1930
- case 'version':
1931
- return VersionColumn
1932
- case 'glide_list':
1933
- return ListColumn
1934
- case 'image':
1935
- return BasicImageColumn
1936
- case 'int':
1937
- case 'string_types':
1938
- case 'approval_rules':
1939
- case 'audio':
1940
- case 'auto_increment':
1941
- case 'auto_number':
1942
- case 'bootstrap_color':
1943
- case 'breakdown_element':
1944
- case 'catalog_preview':
1945
- case 'char':
1946
- case 'collection':
1947
- case 'color':
1948
- case 'color_display':
1949
- case 'composite_field':
1950
- case 'composite_name':
1951
- case 'compressed':
1952
- case 'condition_string':
1953
- case 'counter':
1954
- case 'css':
1955
- case 'currency':
1956
- case 'currency2':
1957
- case 'data_array':
1958
- case 'data_object':
1959
- case 'data_structure':
1960
- case 'days_of_week':
1961
- case 'day_of_week':
1962
- case 'documentation_field':
1963
- case 'dynamic_json':
1964
- case 'email':
1965
- case 'email_script':
1966
- case 'expression':
1967
- case 'external_names':
1968
- case 'field_list':
1969
- case 'file_attachment':
1970
- case 'float':
1971
- case 'formula':
1972
- case 'geo_point':
1973
- case 'glide_action_list':
1974
- case 'glide_duration':
1975
- case 'glide_precise_time':
1976
- case 'glide_time':
1977
- case 'glide_utc_time':
1978
- case 'glide_var':
1979
- case 'glyphicon':
1980
- case 'graphql_schema':
1981
- case 'GUID':
1982
- case 'html':
1983
- case 'html_script':
1984
- case 'html_template':
1985
- case 'icon':
1986
- case 'index_name':
1987
- case 'insert_timestamp':
1988
- case 'integer_time':
1989
- case 'internal_type':
1990
- case 'ip_addr':
1991
- case 'ip_address':
1992
- case 'journal':
1993
- case 'journal_input':
1994
- case 'journal_list':
1995
- case 'json':
1996
- case 'json_translations':
1997
- case 'language':
1998
- case 'long':
1999
- case 'longint':
2000
- case 'mask_code':
2001
- case 'metric_absolute':
2002
- case 'metric_counter':
2003
- case 'metric_derive':
2004
- case 'metric_gauge':
2005
- case 'mid_config':
2006
- case 'month_of_year':
2007
- case 'multi_small':
2008
- case 'multi_two_lines':
2009
- case 'name_values':
2010
- case 'nds_icon':
2011
- case 'nl_task_int1':
2012
- case 'order_index':
2013
- case 'password':
2014
- case 'password2':
2015
- case 'percent_complete':
2016
- case 'phone_number':
2017
- case 'phone_number_e164':
2018
- case 'ph_number':
2019
- case 'price':
2020
- case 'properties':
2021
- case 'records':
2022
- case 'reference_name':
2023
- case 'related_tags':
2024
- case 'reminder_field_name':
2025
- case 'repeat_count':
2026
- case 'repeat_type':
2027
- case 'replication_payload':
2028
- case 'schedule_interval_count':
2029
- case 'script_client':
2030
- case 'script_plain':
2031
- case 'script_server':
2032
- case 'short_field_name':
2033
- case 'short_table_name':
2034
- case 'simple_name_values':
2035
- case 'slushbucket':
2036
- case 'snapshot_template_value':
2037
- case 'source_id':
2038
- case 'source_name':
2039
- case 'source_table':
2040
- case 'string_boolean':
2041
- case 'string_full_utf8':
2042
- case 'structure':
2043
- case 'sysevent_name':
2044
- case 'sysrule_field_name':
2045
- case 'sys_class_path':
2046
- case 'template_value':
2047
- case 'time':
2048
- case 'timer':
2049
- case 'translated':
2050
- case 'translated_html':
2051
- case 'tree_code':
2052
- case 'tree_path':
2053
- case 'url':
2054
- case 'user_image':
2055
- case 'user_input':
2056
- case 'variables':
2057
- case 'variable_conditions':
2058
- case 'variable_template_value':
2059
- case 'video':
2060
- case 'week_of_month':
2061
- case 'wide_text':
2062
- case 'wiki_text':
2063
- case 'wms_job':
2064
- case 'workflow':
2065
- case 'workflow_conditions':
2066
- case 'xml':
2067
- default:
2068
- return GenericColumn
2069
- }
2070
- }