@servicenow/sdk-build-plugins 4.4.1 → 4.5.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 (287) hide show
  1. package/dist/acl-plugin.js +54 -4
  2. package/dist/acl-plugin.js.map +1 -1
  3. package/dist/applicability-plugin.js +2 -0
  4. package/dist/applicability-plugin.js.map +1 -1
  5. package/dist/application-menu-plugin.js +2 -0
  6. package/dist/application-menu-plugin.js.map +1 -1
  7. package/dist/arrow-function-plugin.d.ts +6 -1
  8. package/dist/arrow-function-plugin.js +105 -12
  9. package/dist/arrow-function-plugin.js.map +1 -1
  10. package/dist/atf/test-plugin.js +2 -0
  11. package/dist/atf/test-plugin.js.map +1 -1
  12. package/dist/basic-syntax-plugin.js +20 -0
  13. package/dist/basic-syntax-plugin.js.map +1 -1
  14. package/dist/call-expression-plugin.js +1 -0
  15. package/dist/call-expression-plugin.js.map +1 -1
  16. package/dist/claims-plugin.js +1 -0
  17. package/dist/claims-plugin.js.map +1 -1
  18. package/dist/client-script-plugin.js +1 -0
  19. package/dist/client-script-plugin.js.map +1 -1
  20. package/dist/column-plugin.js +1 -0
  21. package/dist/column-plugin.js.map +1 -1
  22. package/dist/cross-scope-privilege-plugin.js +1 -0
  23. package/dist/cross-scope-privilege-plugin.js.map +1 -1
  24. package/dist/dashboard/dashboard-plugin.js +2 -0
  25. package/dist/dashboard/dashboard-plugin.js.map +1 -1
  26. package/dist/data-plugin.js +1 -0
  27. package/dist/data-plugin.js.map +1 -1
  28. package/dist/email-notification-plugin.js +9 -13
  29. package/dist/email-notification-plugin.js.map +1 -1
  30. package/dist/flow/constants/flow-plugin-constants.d.ts +1 -1
  31. package/dist/flow/constants/flow-plugin-constants.js +1 -1
  32. package/dist/flow/constants/flow-plugin-constants.js.map +1 -1
  33. package/dist/flow/flow-logic/flow-logic-plugin-helpers.d.ts +82 -2
  34. package/dist/flow/flow-logic/flow-logic-plugin-helpers.js +48 -40
  35. package/dist/flow/flow-logic/flow-logic-plugin-helpers.js.map +1 -1
  36. package/dist/flow/flow-logic/flow-logic-plugin.js +1 -0
  37. package/dist/flow/flow-logic/flow-logic-plugin.js.map +1 -1
  38. package/dist/flow/plugins/approval-rules-plugin.js +1 -0
  39. package/dist/flow/plugins/approval-rules-plugin.js.map +1 -1
  40. package/dist/flow/plugins/flow-action-definition-plugin.js +4 -2
  41. package/dist/flow/plugins/flow-action-definition-plugin.js.map +1 -1
  42. package/dist/flow/plugins/flow-data-pill-plugin.js +1 -0
  43. package/dist/flow/plugins/flow-data-pill-plugin.js.map +1 -1
  44. package/dist/flow/plugins/flow-definition-plugin.js +8 -3
  45. package/dist/flow/plugins/flow-definition-plugin.js.map +1 -1
  46. package/dist/flow/plugins/flow-diagnostics-plugin.js +1 -0
  47. package/dist/flow/plugins/flow-diagnostics-plugin.js.map +1 -1
  48. package/dist/flow/plugins/flow-instance-plugin.js +68 -12
  49. package/dist/flow/plugins/flow-instance-plugin.js.map +1 -1
  50. package/dist/flow/plugins/flow-trigger-instance-plugin.js +1 -0
  51. package/dist/flow/plugins/flow-trigger-instance-plugin.js.map +1 -1
  52. package/dist/flow/plugins/inline-script-plugin.js +1 -0
  53. package/dist/flow/plugins/inline-script-plugin.js.map +1 -1
  54. package/dist/flow/plugins/step-definition-plugin.js +3 -2
  55. package/dist/flow/plugins/step-definition-plugin.js.map +1 -1
  56. package/dist/flow/plugins/step-instance-plugin.js +1 -0
  57. package/dist/flow/plugins/step-instance-plugin.js.map +1 -1
  58. package/dist/flow/plugins/trigger-plugin.js +2 -0
  59. package/dist/flow/plugins/trigger-plugin.js.map +1 -1
  60. package/dist/flow/plugins/wfa-datapill-plugin.js +1 -0
  61. package/dist/flow/plugins/wfa-datapill-plugin.js.map +1 -1
  62. package/dist/flow/post-install.d.ts +2 -0
  63. package/dist/flow/post-install.js +58 -0
  64. package/dist/flow/post-install.js.map +1 -0
  65. package/dist/flow/utils/complex-objects.js +4 -2
  66. package/dist/flow/utils/complex-objects.js.map +1 -1
  67. package/dist/flow/utils/flow-constants.d.ts +24 -0
  68. package/dist/flow/utils/flow-constants.js +29 -2
  69. package/dist/flow/utils/flow-constants.js.map +1 -1
  70. package/dist/flow/utils/flow-to-xml.d.ts +3 -2
  71. package/dist/flow/utils/flow-to-xml.js +3 -4
  72. package/dist/flow/utils/flow-to-xml.js.map +1 -1
  73. package/dist/flow/utils/label-cache-processor.d.ts +5 -0
  74. package/dist/flow/utils/label-cache-processor.js +14 -2
  75. package/dist/flow/utils/label-cache-processor.js.map +1 -1
  76. package/dist/flow/utils/service-catalog.js +5 -1
  77. package/dist/flow/utils/service-catalog.js.map +1 -1
  78. package/dist/form-plugin.d.ts +2 -0
  79. package/dist/form-plugin.js +1134 -0
  80. package/dist/form-plugin.js.map +1 -0
  81. package/dist/html-import-plugin.js +1 -0
  82. package/dist/html-import-plugin.js.map +1 -1
  83. package/dist/import-sets-plugin.js +2 -0
  84. package/dist/import-sets-plugin.js.map +1 -1
  85. package/dist/index.d.ts +9 -0
  86. package/dist/index.js +13 -1
  87. package/dist/index.js.map +1 -1
  88. package/dist/instance-scan-plugin.d.ts +2 -0
  89. package/dist/instance-scan-plugin.js +298 -0
  90. package/dist/instance-scan-plugin.js.map +1 -0
  91. package/dist/json-plugin.js +1 -0
  92. package/dist/json-plugin.js.map +1 -1
  93. package/dist/list-plugin.js +1 -0
  94. package/dist/list-plugin.js.map +1 -1
  95. package/dist/now-attach-plugin.js +1 -0
  96. package/dist/now-attach-plugin.js.map +1 -1
  97. package/dist/now-config-plugin.js +659 -51
  98. package/dist/now-config-plugin.js.map +1 -1
  99. package/dist/now-id-plugin.js +1 -0
  100. package/dist/now-id-plugin.js.map +1 -1
  101. package/dist/now-include-plugin.js +1 -0
  102. package/dist/now-include-plugin.js.map +1 -1
  103. package/dist/now-ref-plugin.js +1 -0
  104. package/dist/now-ref-plugin.js.map +1 -1
  105. package/dist/now-unresolved-plugin.js +1 -0
  106. package/dist/now-unresolved-plugin.js.map +1 -1
  107. package/dist/package-json-plugin.js +1 -0
  108. package/dist/package-json-plugin.js.map +1 -1
  109. package/dist/property-plugin.js +3 -1
  110. package/dist/property-plugin.js.map +1 -1
  111. package/dist/record-plugin.d.ts +30 -0
  112. package/dist/record-plugin.js +37 -1
  113. package/dist/record-plugin.js.map +1 -1
  114. package/dist/repack/lint/Rules.d.ts +11 -2
  115. package/dist/repack/lint/Rules.js +160 -16
  116. package/dist/repack/lint/Rules.js.map +1 -1
  117. package/dist/repack/lint/index.d.ts +10 -5
  118. package/dist/repack/lint/index.js +76 -50
  119. package/dist/repack/lint/index.js.map +1 -1
  120. package/dist/rest-api-plugin.js +14 -0
  121. package/dist/rest-api-plugin.js.map +1 -1
  122. package/dist/role-plugin.js +1 -0
  123. package/dist/role-plugin.js.map +1 -1
  124. package/dist/schedule-script/index.d.ts +1 -0
  125. package/dist/schedule-script/index.js +18 -0
  126. package/dist/schedule-script/index.js.map +1 -0
  127. package/dist/schedule-script/scheduled-script-plugin.d.ts +2 -0
  128. package/dist/schedule-script/scheduled-script-plugin.js +551 -0
  129. package/dist/schedule-script/scheduled-script-plugin.js.map +1 -0
  130. package/dist/schedule-script/timeZoneConverter.d.ts +61 -0
  131. package/dist/schedule-script/timeZoneConverter.js +170 -0
  132. package/dist/schedule-script/timeZoneConverter.js.map +1 -0
  133. package/dist/script-action-plugin.js +2 -0
  134. package/dist/script-action-plugin.js.map +1 -1
  135. package/dist/script-include-plugin.js +2 -0
  136. package/dist/script-include-plugin.js.map +1 -1
  137. package/dist/server-module-plugin/index.js +13 -2
  138. package/dist/server-module-plugin/index.js.map +1 -1
  139. package/dist/service-catalog/catalog-clientscript-plugin.js +2 -0
  140. package/dist/service-catalog/catalog-clientscript-plugin.js.map +1 -1
  141. package/dist/service-catalog/catalog-item-plugin.js +2 -0
  142. package/dist/service-catalog/catalog-item-plugin.js.map +1 -1
  143. package/dist/service-catalog/catalog-ui-policy-plugin.js +2 -0
  144. package/dist/service-catalog/catalog-ui-policy-plugin.js.map +1 -1
  145. package/dist/service-catalog/sc-record-producer-plugin.js +2 -0
  146. package/dist/service-catalog/sc-record-producer-plugin.js.map +1 -1
  147. package/dist/service-catalog/service-catalog-diagnostics.d.ts +6 -0
  148. package/dist/service-catalog/service-catalog-diagnostics.js +20 -0
  149. package/dist/service-catalog/service-catalog-diagnostics.js.map +1 -1
  150. package/dist/service-catalog/shape-to-record.js +7 -2
  151. package/dist/service-catalog/shape-to-record.js.map +1 -1
  152. package/dist/service-catalog/variable-set-plugin.js +2 -0
  153. package/dist/service-catalog/variable-set-plugin.js.map +1 -1
  154. package/dist/service-portal/angular-provider-plugin.js +2 -0
  155. package/dist/service-portal/angular-provider-plugin.js.map +1 -1
  156. package/dist/service-portal/dependency-plugin.js +5 -31
  157. package/dist/service-portal/dependency-plugin.js.map +1 -1
  158. package/dist/service-portal/menu-plugin.d.ts +2 -0
  159. package/dist/service-portal/menu-plugin.js +353 -0
  160. package/dist/service-portal/menu-plugin.js.map +1 -0
  161. package/dist/service-portal/page-plugin.d.ts +2 -0
  162. package/dist/service-portal/page-plugin.js +702 -0
  163. package/dist/service-portal/page-plugin.js.map +1 -0
  164. package/dist/service-portal/portal-plugin.d.ts +2 -0
  165. package/dist/service-portal/portal-plugin.js +296 -0
  166. package/dist/service-portal/portal-plugin.js.map +1 -0
  167. package/dist/service-portal/theme-plugin.d.ts +2 -0
  168. package/dist/service-portal/theme-plugin.js +112 -0
  169. package/dist/service-portal/theme-plugin.js.map +1 -0
  170. package/dist/service-portal/utils.d.ts +8 -0
  171. package/dist/service-portal/utils.js +50 -0
  172. package/dist/service-portal/utils.js.map +1 -0
  173. package/dist/service-portal/widget-plugin.js +45 -8
  174. package/dist/service-portal/widget-plugin.js.map +1 -1
  175. package/dist/sla-plugin.js +2 -0
  176. package/dist/sla-plugin.js.map +1 -1
  177. package/dist/static-content-plugin.js +1 -0
  178. package/dist/static-content-plugin.js.map +1 -1
  179. package/dist/table-plugin.js +1 -0
  180. package/dist/table-plugin.js.map +1 -1
  181. package/dist/ui-action-plugin.js +2 -0
  182. package/dist/ui-action-plugin.js.map +1 -1
  183. package/dist/ui-page-plugin.js +33 -8
  184. package/dist/ui-page-plugin.js.map +1 -1
  185. package/dist/ui-policy-plugin.js +1 -0
  186. package/dist/ui-policy-plugin.js.map +1 -1
  187. package/dist/user-preference-plugin.js +2 -0
  188. package/dist/user-preference-plugin.js.map +1 -1
  189. package/dist/utils.d.ts +20 -2
  190. package/dist/utils.js +34 -3
  191. package/dist/utils.js.map +1 -1
  192. package/dist/ux-list-menu-config-plugin.js +2 -0
  193. package/dist/ux-list-menu-config-plugin.js.map +1 -1
  194. package/dist/view-plugin.js +1 -0
  195. package/dist/view-plugin.js.map +1 -1
  196. package/dist/workspace-plugin.js +2 -0
  197. package/dist/workspace-plugin.js.map +1 -1
  198. package/package.json +10 -11
  199. package/src/_types/eslint-community-eslint-utils.d.ts +15 -0
  200. package/src/acl-plugin.ts +97 -8
  201. package/src/applicability-plugin.ts +2 -0
  202. package/src/application-menu-plugin.ts +2 -0
  203. package/src/arrow-function-plugin.ts +128 -13
  204. package/src/atf/test-plugin.ts +2 -0
  205. package/src/basic-syntax-plugin.ts +21 -0
  206. package/src/call-expression-plugin.ts +1 -0
  207. package/src/claims-plugin.ts +1 -0
  208. package/src/client-script-plugin.ts +2 -1
  209. package/src/column-plugin.ts +1 -0
  210. package/src/cross-scope-privilege-plugin.ts +2 -1
  211. package/src/dashboard/dashboard-plugin.ts +2 -0
  212. package/src/data-plugin.ts +1 -0
  213. package/src/email-notification-plugin.ts +3 -23
  214. package/src/flow/constants/flow-plugin-constants.ts +1 -1
  215. package/src/flow/flow-logic/flow-logic-plugin-helpers.ts +47 -45
  216. package/src/flow/flow-logic/flow-logic-plugin.ts +1 -0
  217. package/src/flow/plugins/approval-rules-plugin.ts +1 -0
  218. package/src/flow/plugins/flow-action-definition-plugin.ts +4 -2
  219. package/src/flow/plugins/flow-data-pill-plugin.ts +1 -0
  220. package/src/flow/plugins/flow-definition-plugin.ts +10 -4
  221. package/src/flow/plugins/flow-diagnostics-plugin.ts +1 -0
  222. package/src/flow/plugins/flow-instance-plugin.ts +103 -14
  223. package/src/flow/plugins/flow-trigger-instance-plugin.ts +1 -0
  224. package/src/flow/plugins/inline-script-plugin.ts +1 -0
  225. package/src/flow/plugins/step-definition-plugin.ts +3 -2
  226. package/src/flow/plugins/step-instance-plugin.ts +1 -0
  227. package/src/flow/plugins/trigger-plugin.ts +2 -0
  228. package/src/flow/plugins/wfa-datapill-plugin.ts +1 -0
  229. package/src/flow/post-install.ts +92 -0
  230. package/src/flow/utils/complex-objects.ts +10 -2
  231. package/src/flow/utils/flow-constants.ts +30 -1
  232. package/src/flow/utils/flow-to-xml.ts +4 -4
  233. package/src/flow/utils/label-cache-processor.ts +14 -2
  234. package/src/flow/utils/service-catalog.ts +5 -2
  235. package/src/form-plugin.ts +1411 -0
  236. package/src/html-import-plugin.ts +1 -0
  237. package/src/import-sets-plugin.ts +2 -0
  238. package/src/index.ts +9 -0
  239. package/src/instance-scan-plugin.ts +318 -0
  240. package/src/json-plugin.ts +1 -0
  241. package/src/list-plugin.ts +2 -1
  242. package/src/now-attach-plugin.ts +1 -0
  243. package/src/now-config-plugin.ts +833 -53
  244. package/src/now-id-plugin.ts +1 -0
  245. package/src/now-include-plugin.ts +1 -0
  246. package/src/now-ref-plugin.ts +1 -0
  247. package/src/now-unresolved-plugin.ts +1 -0
  248. package/src/package-json-plugin.ts +1 -0
  249. package/src/property-plugin.ts +3 -1
  250. package/src/record-plugin.ts +42 -2
  251. package/src/repack/lint/Rules.ts +171 -22
  252. package/src/repack/lint/index.ts +80 -56
  253. package/src/rest-api-plugin.ts +21 -1
  254. package/src/role-plugin.ts +2 -1
  255. package/src/schedule-script/index.ts +1 -0
  256. package/src/schedule-script/scheduled-script-plugin.ts +679 -0
  257. package/src/schedule-script/timeZoneConverter.ts +188 -0
  258. package/src/script-action-plugin.ts +2 -0
  259. package/src/script-include-plugin.ts +2 -0
  260. package/src/server-module-plugin/index.ts +14 -2
  261. package/src/service-catalog/catalog-clientscript-plugin.ts +2 -0
  262. package/src/service-catalog/catalog-item-plugin.ts +2 -0
  263. package/src/service-catalog/catalog-ui-policy-plugin.ts +2 -0
  264. package/src/service-catalog/sc-record-producer-plugin.ts +2 -0
  265. package/src/service-catalog/service-catalog-diagnostics.ts +30 -0
  266. package/src/service-catalog/shape-to-record.ts +8 -2
  267. package/src/service-catalog/variable-set-plugin.ts +2 -0
  268. package/src/service-portal/angular-provider-plugin.ts +2 -0
  269. package/src/service-portal/dependency-plugin.ts +6 -53
  270. package/src/service-portal/menu-plugin.ts +435 -0
  271. package/src/service-portal/page-plugin.ts +830 -0
  272. package/src/service-portal/portal-plugin.ts +319 -0
  273. package/src/service-portal/theme-plugin.ts +135 -0
  274. package/src/service-portal/utils.ts +69 -0
  275. package/src/service-portal/widget-plugin.ts +79 -9
  276. package/src/sla-plugin.ts +2 -0
  277. package/src/static-content-plugin.ts +1 -0
  278. package/src/table-plugin.ts +2 -1
  279. package/src/ui-action-plugin.ts +2 -0
  280. package/src/ui-page-plugin.ts +34 -8
  281. package/src/ui-policy-plugin.ts +2 -1
  282. package/src/user-preference-plugin.ts +2 -0
  283. package/src/utils.ts +42 -2
  284. package/src/ux-list-menu-config-plugin.ts +2 -0
  285. package/src/view-plugin.ts +1 -0
  286. package/src/workspace-plugin.ts +2 -0
  287. package/src/_types/eslint-plugin-es-x.d.ts +0 -17
@@ -0,0 +1,435 @@
1
+ import {
2
+ CallExpressionShape,
3
+ Plugin,
4
+ type Diagnostics,
5
+ type Factory,
6
+ type Record,
7
+ type Shape,
8
+ type Transform,
9
+ } from '@servicenow/sdk-build-core'
10
+ import { NowIdShape } from '../now-id-plugin'
11
+ import { NowIncludeShape } from '../now-include-plugin'
12
+ import { toReference, getFieldAsNumber, noThrow, createSdkDocEntry } from '../utils'
13
+
14
+ const default_placeholder_dimensions = `{
15
+ "mobile": {
16
+ "height": "250px",
17
+ "width": "100%"
18
+ },
19
+ "desktop": {
20
+ "height": "250px",
21
+ "width": "100%"
22
+ },
23
+ "tablet": {
24
+ "height": "250px",
25
+ "width": "100%"
26
+ }
27
+ }`
28
+
29
+ const default_placeholder_template = `<!--
30
+ AngularJS template with configurable options.
31
+ Use the "options" object to control dynamic behavior.
32
+ Example: Display an element when max row count is 10:
33
+ <div ng-if="options.maxRowCount === 10"></div>
34
+ The "skeleton-container" class is used for loading placeholders.
35
+ -->
36
+ <div class="skeleton-container">
37
+ <!-- Header Skeleton -->
38
+ <div class="skeleton-box skeleton-header"></div>
39
+ <!-- Body Skeleton -->
40
+ <div class="skeleton-box skeleton-line"></div>
41
+ <div class="skeleton-box skeleton-line small"></div>
42
+ <div class="skeleton-box skeleton-line medium"></div>
43
+ </div>`
44
+
45
+ const default_placeholder_script = `function evaluateConfig(options) { return {
46
+ "mobile": {
47
+ "height": "250px",
48
+ "width": "100%"
49
+ },
50
+ "desktop": {
51
+ "height": "250px",
52
+ "width": "100%"
53
+ },
54
+ "tablet": {
55
+ "height": "250px",
56
+ "width": "100%"
57
+ }
58
+ }; }`
59
+
60
+ const defaultValues = {
61
+ menuItem: {
62
+ type: 'page',
63
+ order: 100,
64
+ active: true,
65
+ color: 'default',
66
+ size: 'md',
67
+ },
68
+ menu: {
69
+ active: true,
70
+ color: 'default',
71
+ size: 'md',
72
+ asyncLoadDeviceType: 'desktop,tablet,mobile',
73
+ },
74
+ }
75
+
76
+ function getRolesString(rolesShape: Shape, diagnostics: Diagnostics): string {
77
+ const roles = rolesShape
78
+ ?.ifArray()
79
+ ?.map((role) => {
80
+ if (role.isString()) {
81
+ return role.getValue()
82
+ }
83
+ if (role.isRecord()) {
84
+ const name = role.get('name')
85
+ if (name?.isString()) {
86
+ return name.getValue()
87
+ }
88
+ return role.getId()
89
+ }
90
+
91
+ diagnostics.error(role, `roles must be strings or role records`)
92
+ return undefined
93
+ })
94
+ .filter((r) => r) as string[] | undefined
95
+
96
+ return roles?.toString() ?? ''
97
+ }
98
+
99
+ const addProperty = (obj: { [key: string]: unknown }, key: string, value: unknown) => {
100
+ if (
101
+ value === undefined ||
102
+ (Array.isArray(value) && value.length === 0) ||
103
+ (typeof value === 'string' && value === '')
104
+ ) {
105
+ return
106
+ }
107
+
108
+ obj[key] = value
109
+ }
110
+
111
+ async function getMenuItem(item: Record, transform: Transform) {
112
+ const obj: { [key: string]: unknown } = {}
113
+
114
+ addProperty(obj, '$id', NowIdShape.from(item))
115
+ addProperty(obj, 'label', item.get('label'))
116
+ addProperty(obj, 'order', getFieldAsNumber(item, 'order', 100))
117
+ addProperty(obj, 'active', item.get('active').toBoolean())
118
+ addProperty(obj, 'glyph', item.get('glyph')?.ifString()?.getValue())
119
+ addProperty(obj, 'color', item.get('color')?.ifString()?.getValue())
120
+ addProperty(obj, 'hint', item.get('hint')?.ifString()?.getValue())
121
+ addProperty(obj, 'shortDescription', item.get('short_description')?.ifString()?.getValue())
122
+ addProperty(obj, 'condition', item.get('condition')?.ifString()?.getValue())
123
+ addProperty(obj, 'type', item.get('type'))
124
+
125
+ const roles = item.get('roles')
126
+ const rolesStr = roles.ifString()?.getValue() ?? ''
127
+ if (rolesStr) {
128
+ addProperty(obj, 'roles', rolesStr.split(','))
129
+ }
130
+
131
+ // Convert all type-specific fields unconditionally to ensure round-trip data preservation
132
+ const spPage = item.get('sp_page')
133
+ if (spPage?.ifString()?.getValue()) {
134
+ addProperty(obj, 'page', toReference(spPage))
135
+ }
136
+
137
+ addProperty(obj, 'url', item.get('url')?.ifString()?.getValue())
138
+ addProperty(obj, 'urlTarget', item.get('url_target')?.ifString()?.getValue())
139
+
140
+ const scCategory = item.get('sc_category')
141
+ if (scCategory?.ifString()?.getValue()) {
142
+ addProperty(obj, 'scCategory', toReference(scCategory))
143
+ }
144
+
145
+ const scCatItem = item.get('sc_cat_item')
146
+ if (scCatItem?.ifString()?.getValue()) {
147
+ addProperty(obj, 'catItem', toReference(scCatItem))
148
+ }
149
+
150
+ addProperty(obj, 'kbTopic', item.get('kb_topic')?.ifString()?.getValue())
151
+
152
+ const kbArticle = item.get('kb_article')
153
+ if (kbArticle?.ifString()?.getValue()) {
154
+ addProperty(obj, 'kbArticle', toReference(kbArticle))
155
+ }
156
+
157
+ const kbCategory = item.get('kb_category')
158
+ if (kbCategory?.ifString()?.getValue()) {
159
+ addProperty(obj, 'kbCategory', toReference(kbCategory))
160
+ }
161
+
162
+ addProperty(obj, 'table', item.get('table')?.ifString()?.getValue())
163
+ addProperty(obj, 'filter', item.get('filter')?.ifString()?.getValue())
164
+ addProperty(obj, 'display1', item.get('display_1')?.ifString()?.getValue())
165
+ addProperty(obj, 'display2', item.get('display_2')?.ifString()?.getValue())
166
+ addProperty(obj, 'displayDate', item.get('display_date')?.ifString()?.getValue())
167
+ // Handle Now.include support for script field
168
+ const recordScript = item.get('record_script')?.ifString()?.getValue()
169
+ if (recordScript && recordScript.trim() !== '') {
170
+ const script = await NowIncludeShape.fromRecord(item, item.get('record_script'), transform)
171
+ addProperty(obj, 'script', script)
172
+ }
173
+
174
+ return obj
175
+ }
176
+
177
+ async function createItemRecords(
178
+ itemsShape: Shape,
179
+ menuId: Shape | undefined,
180
+ parentItemId: Shape | undefined,
181
+ factory: Factory,
182
+ diagnostics: Diagnostics
183
+ ): Promise<Record[]> {
184
+ const items = itemsShape?.ifArray()?.getElements() ?? []
185
+ const created: Record[] = []
186
+
187
+ for (const item of items) {
188
+ const obj = item.asObject()
189
+ const type = obj.get('type').asString().getValue()
190
+
191
+ const itemRecord = await factory.createRecord({
192
+ source: item,
193
+ table: 'sp_rectangle_menu_item',
194
+ explicitId: obj.get('$id'),
195
+ properties: {
196
+ label: obj.get('label')?.ifString()?.getValue() ?? '',
197
+ order: obj.get('order').ifNumber()?.getValue() ?? defaultValues.menuItem.order,
198
+ active: obj.get('active')?.ifBoolean()?.getValue() ?? defaultValues.menuItem.active,
199
+ glyph: obj.get('glyph')?.ifString()?.getValue() ?? 'empty',
200
+ color: obj.get('color')?.ifString()?.getValue() ?? defaultValues.menuItem.color,
201
+ hint: obj.get('hint')?.ifString()?.getValue() ?? '',
202
+ short_description: obj.get('shortDescription')?.ifString()?.getValue() ?? '',
203
+ condition: obj.get('condition')?.ifString()?.getValue() ?? '',
204
+ type,
205
+ sp_rectangle_menu: menuId ?? '',
206
+ sp_rectangle_menu_item: parentItemId ?? '',
207
+ sp_page: obj.get('page') ? toReference(obj.get('page')) : '',
208
+ url: obj.get('url')?.ifString()?.getValue() ?? '',
209
+ url_target: obj.get('urlTarget')?.ifString()?.getValue() ?? '',
210
+ sc_category: obj.get('scCategory') ? toReference(obj.get('scCategory')) : '',
211
+ sc_cat_item: obj.get('catItem') ? toReference(obj.get('catItem')) : '',
212
+ kb_topic: obj.get('kbTopic')?.ifString()?.getValue() ?? '',
213
+ kb_article: obj.get('kbArticle') ? toReference(obj.get('kbArticle')) : '',
214
+ kb_category: obj.get('kbCategory') ? toReference(obj.get('kbCategory')) : '',
215
+ table: obj.get('table')?.ifString()?.getValue() ?? '',
216
+ filter: obj.get('filter')?.ifString()?.getValue() ?? '',
217
+ display_1: obj.get('display1')?.ifString()?.getValue() ?? '',
218
+ display_2: obj.get('display2')?.ifString()?.getValue() ?? '',
219
+ display_date: obj.get('displayDate')?.ifString()?.getValue() ?? '',
220
+ record_script: obj.get('script')?.ifString()?.getValue() ?? '',
221
+ roles: getRolesString(obj.get('roles'), diagnostics),
222
+ },
223
+ })
224
+
225
+ created.push(itemRecord)
226
+
227
+ const childItems = obj.get('childItems')
228
+ if (childItems?.isDefined()) {
229
+ const childRecords = await createItemRecords(
230
+ childItems,
231
+ undefined,
232
+ itemRecord.getId(),
233
+ factory,
234
+ diagnostics
235
+ )
236
+ created.push(...childRecords)
237
+ }
238
+ }
239
+ return created
240
+ }
241
+
242
+ export const SPMenuPlugin = Plugin.create({
243
+ name: 'SPMenuPlugin',
244
+ docs: [createSdkDocEntry('SPMenu', ['sp_instance_menu'])],
245
+ records: {
246
+ sp_instance_menu: {
247
+ relationships: {
248
+ sp_rectangle_menu_item: {
249
+ via: 'sp_rectangle_menu',
250
+ descendant: true,
251
+ relationships: {
252
+ sp_rectangle_menu_item: {
253
+ via: 'sp_rectangle_menu_item',
254
+ descendant: true,
255
+ },
256
+ },
257
+ },
258
+ },
259
+
260
+ async toShape(record, { descendants, transform }) {
261
+ const items = descendants.query('sp_rectangle_menu_item', { sp_rectangle_menu: record.getId() })
262
+
263
+ const menuItems = await Promise.all(
264
+ items.map(async (item) => {
265
+ const itemId = item.getId()
266
+ const childItems = descendants.query('sp_rectangle_menu_item', {
267
+ sp_rectangle_menu_item: itemId,
268
+ })
269
+ const childMenuItems = await Promise.all(
270
+ childItems.map(async (childItem) => {
271
+ return await getMenuItem(childItem, transform)
272
+ })
273
+ )
274
+
275
+ const menuItem = {
276
+ ...(await getMenuItem(item, transform)),
277
+ }
278
+
279
+ if (childMenuItems.length > 0) {
280
+ menuItem['childItems'] = childMenuItems
281
+ }
282
+
283
+ return menuItem
284
+ })
285
+ )
286
+
287
+ const rolesField = record.get('roles')
288
+ const roleStr = rolesField?.ifString()?.getValue()
289
+ let rolesArray: string[] | undefined
290
+
291
+ if (roleStr && roleStr !== '') {
292
+ const filteredRoles = roleStr.split(',').filter((r) => r !== '')
293
+ if (filteredRoles.length > 0) {
294
+ rolesArray = filteredRoles
295
+ }
296
+ }
297
+
298
+ const asyncLoadTrigger =
299
+ record.get('async_load_trigger')?.ifString()?.ifNotEmpty()?.getValue() ?? 'viewport'
300
+ const asyncLoadDeviceType = record.get('async_load_device_type')?.ifString()?.getValue() ?? ''
301
+
302
+ return {
303
+ success: true,
304
+ value: new CallExpressionShape({
305
+ source: record,
306
+ callee: 'SPMenu',
307
+ args: [
308
+ record.transform(({ $ }) => ({
309
+ $id: $.val(NowIdShape.from(record)),
310
+ title: $,
311
+ id: $.from('id').def(''),
312
+ widget: $.from('sp_widget'),
313
+ column: $.from('sp_column'),
314
+ active: $.toBoolean().def(true),
315
+ widgetParameters: $.from('widget_parameters')
316
+ .map((d) => {
317
+ const json = d.ifString()?.getValue()
318
+ if (!json) {
319
+ return ''
320
+ }
321
+
322
+ const parsed = noThrow(() => JSON.parse(json))
323
+ return parsed instanceof Error ? json : parsed
324
+ })
325
+ .def(''),
326
+ css: $.def(''),
327
+ url: $.def(''),
328
+ glyph: $.def(''),
329
+ size: $.def('md'),
330
+ color: $.def('default'),
331
+ cssClass: $.from('class_name').def(''),
332
+ order: $.from('order').toNumber().def(1),
333
+ roles: $.val(rolesArray),
334
+ shortDescription: $.from('short_description').def(''),
335
+ asyncLoad: $.from('async_load').toBoolean().def(false),
336
+ preservePlaceholderSize: $.from('preserve_placeholder_size').toBoolean().def(false),
337
+ advancedPlaceholderDimensions: $.from('advanced_placeholder_dimensions')
338
+ .toBoolean()
339
+ .def(false),
340
+ placeholderDimensions: $.from('placeholder_dimensions')
341
+ .map((d) => {
342
+ const json = d.ifString()?.getValue()
343
+
344
+ const parsed = noThrow(() => json && JSON.parse(json))
345
+ return parsed instanceof Error ? json : parsed
346
+ })
347
+ .def(''),
348
+ placeholderConfigurationScript: $.from('placeholder_dimensions_script').def(
349
+ default_placeholder_script
350
+ ),
351
+ placeholderTemplate: $.from('placeholder_template').def(default_placeholder_template),
352
+ items: $.val(menuItems),
353
+ asyncLoadTrigger: $.val(asyncLoadTrigger),
354
+ asyncLoadDeviceType: $.val(asyncLoadDeviceType),
355
+ })),
356
+ ],
357
+ }),
358
+ }
359
+ },
360
+ },
361
+ },
362
+ shapes: [
363
+ {
364
+ shape: CallExpressionShape,
365
+ fileTypes: ['fluent'],
366
+ async toRecord(callExpression, { factory, diagnostics }) {
367
+ if (callExpression.getCallee() !== 'SPMenu') {
368
+ return { success: false }
369
+ }
370
+
371
+ const menu = callExpression.getArgument(0).asObject()
372
+
373
+ // Process roles if they exist as an array
374
+ const roles = menu.get('roles')
375
+ const rolesString = getRolesString(roles, diagnostics)
376
+
377
+ const menuRecord = await factory.createRecord({
378
+ source: callExpression,
379
+ table: 'sp_instance_menu',
380
+ explicitId: menu.get('$id'),
381
+ properties: menu.transform(({ $ }) => ({
382
+ title: $,
383
+ id: $,
384
+ sp_widget: $.from('widget').map(toReference).def(''),
385
+ sp_column: $.from('column').map(toReference).def(''),
386
+ widget_parameters: $.from('widgetParameters')
387
+ .map((v) =>
388
+ v.ifString() || v instanceof NowIncludeShape ? v : JSON.stringify(v.getValue())
389
+ )
390
+ .def(''),
391
+ css: $.def(''),
392
+ url: $.def(''),
393
+ glyph: $.def(''),
394
+ size: $.def('md'),
395
+ color: $.def('default'),
396
+ class_name: $.from('cssClass').def(''),
397
+ active: $.toBoolean().def(true),
398
+ order: $.toNumber().def(1),
399
+ roles: $.val(rolesString),
400
+ short_description: $.from('shortDescription').def(''),
401
+ async_load: $.from('asyncLoad').toBoolean().def(false),
402
+ async_load_trigger: $.from('asyncLoadTrigger').def('viewport'),
403
+ async_load_device_type: $.from('asyncLoadDeviceType').def(
404
+ defaultValues.menu.asyncLoadDeviceType
405
+ ),
406
+ preserve_placeholder_size: $.from('preservePlaceholderSize').toBoolean().def(false),
407
+ placeholder_dimensions: $.from('placeholderDimensions')
408
+ .map((v) =>
409
+ v.ifString() || v instanceof NowIncludeShape ? v : JSON.stringify(v.getValue())
410
+ )
411
+ .def(default_placeholder_dimensions),
412
+ advanced_placeholder_dimensions: $.from('advancedPlaceholderDimensions').toBoolean().def(false),
413
+ placeholder_dimensions_script: $.from('placeholderConfigurationScript').def(
414
+ default_placeholder_script
415
+ ),
416
+ placeholder_template: $.from('placeholderTemplate').def(default_placeholder_template),
417
+ })),
418
+ })
419
+
420
+ const itemRecords = await createItemRecords(
421
+ menu.get('items'),
422
+ menuRecord.getId(),
423
+ undefined,
424
+ factory,
425
+ diagnostics
426
+ )
427
+
428
+ return {
429
+ success: true,
430
+ value: menuRecord.with(...itemRecords),
431
+ }
432
+ },
433
+ },
434
+ ],
435
+ })