@servicenow/sdk-build-plugins 2.0.1
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.
- package/dist/AttachmentPlugin.d.ts +253 -0
- package/dist/AttachmentPlugin.js +216 -0
- package/dist/AttachmentPlugin.js.map +1 -0
- package/dist/BusinessRulePlugin.d.ts +56 -0
- package/dist/BusinessRulePlugin.js +171 -0
- package/dist/BusinessRulePlugin.js.map +1 -0
- package/dist/CrossScopePrivilegePlugin.d.ts +22 -0
- package/dist/CrossScopePrivilegePlugin.js +42 -0
- package/dist/CrossScopePrivilegePlugin.js.map +1 -0
- package/dist/DefaultPlugin.d.ts +71 -0
- package/dist/DefaultPlugin.js +238 -0
- package/dist/DefaultPlugin.js.map +1 -0
- package/dist/IdPlugin.d.ts +17 -0
- package/dist/IdPlugin.js +45 -0
- package/dist/IdPlugin.js.map +1 -0
- package/dist/ListPlugin.d.ts +91 -0
- package/dist/ListPlugin.js +398 -0
- package/dist/ListPlugin.js.map +1 -0
- package/dist/PropertyPlugin.d.ts +122 -0
- package/dist/PropertyPlugin.js +165 -0
- package/dist/PropertyPlugin.js.map +1 -0
- package/dist/ScriptTemplatePlugin.d.ts +31 -0
- package/dist/ScriptTemplatePlugin.js +208 -0
- package/dist/ScriptTemplatePlugin.js.map +1 -0
- package/dist/UserPreferencePlugin.d.ts +16 -0
- package/dist/UserPreferencePlugin.js +30 -0
- package/dist/UserPreferencePlugin.js.map +1 -0
- package/dist/aclAndRole/AclPlugin.d.ts +117 -0
- package/dist/aclAndRole/AclPlugin.js +285 -0
- package/dist/aclAndRole/AclPlugin.js.map +1 -0
- package/dist/aclAndRole/RolePlugin.d.ts +58 -0
- package/dist/aclAndRole/RolePlugin.js +152 -0
- package/dist/aclAndRole/RolePlugin.js.map +1 -0
- package/dist/aclAndRole/Util.d.ts +3 -0
- package/dist/aclAndRole/Util.js +106 -0
- package/dist/aclAndRole/Util.js.map +1 -0
- package/dist/app/ApplicationMenuPlugin.d.ts +32 -0
- package/dist/app/ApplicationMenuPlugin.js +106 -0
- package/dist/app/ApplicationMenuPlugin.js.map +1 -0
- package/dist/atf/ATFComposer.d.ts +492 -0
- package/dist/atf/ATFComposer.js +2717 -0
- package/dist/atf/ATFComposer.js.map +1 -0
- package/dist/atf/TestPlugin.d.ts +31 -0
- package/dist/atf/TestPlugin.js +95 -0
- package/dist/atf/TestPlugin.js.map +1 -0
- package/dist/atf/index.d.ts +1 -0
- package/dist/atf/index.js +9 -0
- package/dist/atf/index.js.map +1 -0
- package/dist/db/ColumnPlugins.d.ts +278 -0
- package/dist/db/ColumnPlugins.js +112 -0
- package/dist/db/ColumnPlugins.js.map +1 -0
- package/dist/db/RecordPlugin.d.ts +208 -0
- package/dist/db/RecordPlugin.js +287 -0
- package/dist/db/RecordPlugin.js.map +1 -0
- package/dist/db/TablePlugin.d.ts +742 -0
- package/dist/db/TablePlugin.js +1249 -0
- package/dist/db/TablePlugin.js.map +1 -0
- package/dist/db/index.d.ts +3 -0
- package/dist/db/index.js +27 -0
- package/dist/db/index.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/scriptedRESTAPI/RESTDeserializationUtils.d.ts +12 -0
- package/dist/scriptedRESTAPI/RESTDeserializationUtils.js +371 -0
- package/dist/scriptedRESTAPI/RESTDeserializationUtils.js.map +1 -0
- package/dist/scriptedRESTAPI/RESTSerializationUtils.d.ts +15 -0
- package/dist/scriptedRESTAPI/RESTSerializationUtils.js +177 -0
- package/dist/scriptedRESTAPI/RESTSerializationUtils.js.map +1 -0
- package/dist/scriptedRESTAPI/RestApiPlugin.d.ts +144 -0
- package/dist/scriptedRESTAPI/RestApiPlugin.js +318 -0
- package/dist/scriptedRESTAPI/RestApiPlugin.js.map +1 -0
- package/dist/scriptedRESTAPI/RestSchemaUtils.d.ts +190 -0
- package/dist/scriptedRESTAPI/RestSchemaUtils.js +53 -0
- package/dist/scriptedRESTAPI/RestSchemaUtils.js.map +1 -0
- package/dist/scriptedRESTAPI/RestUtils.d.ts +75 -0
- package/dist/scriptedRESTAPI/RestUtils.js +469 -0
- package/dist/scriptedRESTAPI/RestUtils.js.map +1 -0
- package/dist/scripts/ClientScriptPlugin.d.ts +43 -0
- package/dist/scripts/ClientScriptPlugin.js +190 -0
- package/dist/scripts/ClientScriptPlugin.js.map +1 -0
- package/dist/scripts/scriptUtils.d.ts +15 -0
- package/dist/scripts/scriptUtils.js +83 -0
- package/dist/scripts/scriptUtils.js.map +1 -0
- package/dist/uxf/ExperiencePlugin.d.ts +22 -0
- package/dist/uxf/ExperiencePlugin.js +55 -0
- package/dist/uxf/ExperiencePlugin.js.map +1 -0
- package/dist/uxf/RoutesPlugin.d.ts +22 -0
- package/dist/uxf/RoutesPlugin.js +176 -0
- package/dist/uxf/RoutesPlugin.js.map +1 -0
- package/dist/uxf/UxfFormulaParser/cleanUxValue.d.ts +4 -0
- package/dist/uxf/UxfFormulaParser/cleanUxValue.js +65 -0
- package/dist/uxf/UxfFormulaParser/cleanUxValue.js.map +1 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/api.d.ts +189 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/api.js +158 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/api.js.map +1 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/clientTransformMap.d.ts +13 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/clientTransformMap.js +604 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/clientTransformMap.js.map +1 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/grammarParser.d.ts +12 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/grammarParser.js +551 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/grammarParser.js.map +1 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/spanHelpers.d.ts +31 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/spanHelpers.js +64 -0
- package/dist/uxf/UxfFormulaParser/grammerParser/spanHelpers.js.map +1 -0
- package/dist/uxf/UxfFormulaParser/index.d.ts +3 -0
- package/dist/uxf/UxfFormulaParser/index.js +11 -0
- package/dist/uxf/UxfFormulaParser/index.js.map +1 -0
- package/dist/uxf/UxfFormulaParser/parser.d.ts +8 -0
- package/dist/uxf/UxfFormulaParser/parser.js +87 -0
- package/dist/uxf/UxfFormulaParser/parser.js.map +1 -0
- package/dist/uxf/UxfFormulaParser/utils/getErrorMsg.d.ts +8 -0
- package/dist/uxf/UxfFormulaParser/utils/getErrorMsg.js +17 -0
- package/dist/uxf/UxfFormulaParser/utils/getErrorMsg.js.map +1 -0
- package/dist/uxf/constants.d.ts +2 -0
- package/dist/uxf/constants.js +8 -0
- package/dist/uxf/constants.js.map +1 -0
- package/dist/uxf/index.d.ts +2 -0
- package/dist/uxf/index.js +11 -0
- package/dist/uxf/index.js.map +1 -0
- package/dist/uxf/tectonicIdGenerator.d.ts +12 -0
- package/dist/uxf/tectonicIdGenerator.js +102 -0
- package/dist/uxf/tectonicIdGenerator.js.map +1 -0
- package/license +9 -0
- package/package.json +42 -0
- package/src/AttachmentPlugin.ts +262 -0
- package/src/BusinessRulePlugin.ts +251 -0
- package/src/CrossScopePrivilegePlugin.ts +54 -0
- package/src/DefaultPlugin.ts +272 -0
- package/src/IdPlugin.ts +47 -0
- package/src/ListPlugin.ts +497 -0
- package/src/PropertyPlugin.ts +218 -0
- package/src/ScriptTemplatePlugin.ts +223 -0
- package/src/UserPreferencePlugin.ts +36 -0
- package/src/aclAndRole/AclPlugin.ts +410 -0
- package/src/aclAndRole/RolePlugin.ts +225 -0
- package/src/aclAndRole/Util.ts +104 -0
- package/src/app/ApplicationMenuPlugin.ts +158 -0
- package/src/atf/ATFComposer.ts +3356 -0
- package/src/atf/TestPlugin.ts +119 -0
- package/src/atf/index.ts +1 -0
- package/src/db/ColumnPlugins.ts +117 -0
- package/src/db/RecordPlugin.ts +391 -0
- package/src/db/TablePlugin.ts +1581 -0
- package/src/db/index.ts +3 -0
- package/src/index.ts +16 -0
- package/src/scriptedRESTAPI/RESTDeserializationUtils.ts +410 -0
- package/src/scriptedRESTAPI/RESTSerializationUtils.ts +227 -0
- package/src/scriptedRESTAPI/RestApiPlugin.ts +438 -0
- package/src/scriptedRESTAPI/RestSchemaUtils.ts +72 -0
- package/src/scriptedRESTAPI/RestUtils.ts +507 -0
- package/src/scripts/ClientScriptPlugin.ts +251 -0
- package/src/scripts/scriptUtils.ts +81 -0
- package/src/uxf/ExperiencePlugin.ts +64 -0
- package/src/uxf/RoutesPlugin.ts +215 -0
- package/src/uxf/UxfFormulaParser/cleanUxValue.ts +73 -0
- package/src/uxf/UxfFormulaParser/grammerParser/api.js +166 -0
- package/src/uxf/UxfFormulaParser/grammerParser/clientTransformMap.js +606 -0
- package/src/uxf/UxfFormulaParser/grammerParser/grammarParser.js +551 -0
- package/src/uxf/UxfFormulaParser/grammerParser/spanHelpers.js +65 -0
- package/src/uxf/UxfFormulaParser/index.ts +4 -0
- package/src/uxf/UxfFormulaParser/parser.ts +64 -0
- package/src/uxf/UxfFormulaParser/utils/getErrorMsg.ts +13 -0
- package/src/uxf/constants.ts +4 -0
- package/src/uxf/index.ts +2 -0
- package/src/uxf/tectonicIdGenerator.ts +81 -0
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
import { List } from '@servicenow/sdk-core/runtime/ui'
|
|
2
|
+
import {
|
|
3
|
+
Plugin,
|
|
4
|
+
PrimitiveData,
|
|
5
|
+
extractCallExpression,
|
|
6
|
+
generateCallExpressionExportForDocument,
|
|
7
|
+
getCallExpressionName,
|
|
8
|
+
getOrCreateEntitySourceFile,
|
|
9
|
+
linkDocument,
|
|
10
|
+
recordXml,
|
|
11
|
+
removeNode,
|
|
12
|
+
unloadBuilder,
|
|
13
|
+
getOrCreatePropertyAssignment,
|
|
14
|
+
setPropertyAssignmentValue,
|
|
15
|
+
getSysUpdateName,
|
|
16
|
+
XmlData,
|
|
17
|
+
writePropertyAsReference,
|
|
18
|
+
getPropertyAssignment,
|
|
19
|
+
addDefaultImportIfAbsent,
|
|
20
|
+
addNamedImportIfAbsent,
|
|
21
|
+
} from '@servicenow/sdk-build-core'
|
|
22
|
+
import { RecordXmlSchema } from './db/RecordPlugin'
|
|
23
|
+
import * as z from 'zod'
|
|
24
|
+
import { SyntaxKind, Node, PropertyAssignment, CallExpression, VariableDeclaration } from 'ts-morph'
|
|
25
|
+
import * as path from 'path'
|
|
26
|
+
import { Diagnostic } from '@servicenow/sdk-project'
|
|
27
|
+
|
|
28
|
+
const DEFAULT_VIEW = 'Default view'
|
|
29
|
+
|
|
30
|
+
type View = {
|
|
31
|
+
id: string
|
|
32
|
+
name: string
|
|
33
|
+
title: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type TransformData = {
|
|
37
|
+
sys_id: string
|
|
38
|
+
view: View
|
|
39
|
+
list: Omit<List, 'columns'>
|
|
40
|
+
table: string
|
|
41
|
+
elements: SysUIListElementXml
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default Plugin({
|
|
45
|
+
name: 'List',
|
|
46
|
+
ownedTables: {
|
|
47
|
+
sys_ui_list: { diagnosticLevel: Diagnostic.Level.Warn },
|
|
48
|
+
},
|
|
49
|
+
extractors: {
|
|
50
|
+
entity: {
|
|
51
|
+
CallExpression(node, context) {
|
|
52
|
+
return extractCallExpression(List, 'list', node, context, (list) =>
|
|
53
|
+
context.keys.registerExplicitId('sys_ui_list', list.$id as string)
|
|
54
|
+
)
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
xml(xml) {
|
|
58
|
+
const result = SysUIListXmlSchema.safeParse(xml.data['record_update'])
|
|
59
|
+
if (!result.success) {
|
|
60
|
+
return undefined
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const {
|
|
64
|
+
data: {
|
|
65
|
+
sys_ui_list: { sys_ui_list, sys_ui_list_element },
|
|
66
|
+
sys_metadata_delete,
|
|
67
|
+
},
|
|
68
|
+
} = result
|
|
69
|
+
|
|
70
|
+
//Delete only gets set on the top level sys_ui_list action attribute, not on sub nodes
|
|
71
|
+
const isDelete = result.data.sys_ui_list['@_action'] === 'DELETE'
|
|
72
|
+
const list = xmlElementToObject(sys_ui_list)
|
|
73
|
+
const elements = toArray(sys_ui_list_element).map(xmlElementToObject)
|
|
74
|
+
let updateName = list['sys_update_name']
|
|
75
|
+
// sys_update_name is not present on the list element, but is present on the delete element on delete payload
|
|
76
|
+
if (isDelete && sys_metadata_delete) {
|
|
77
|
+
const metadataDelete = xmlElementToObject(sys_metadata_delete)
|
|
78
|
+
updateName = metadataDelete['sys_update_name']
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const viewName = sys_ui_list['view']['@_name']
|
|
82
|
+
const view = {
|
|
83
|
+
title: sys_ui_list['view']['@_display_value'],
|
|
84
|
+
name: viewName === 'NULL' ? 'default_view' : viewName,
|
|
85
|
+
id: sys_ui_list['view']['#text'],
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return new XmlData(
|
|
89
|
+
{
|
|
90
|
+
updateName,
|
|
91
|
+
sys_id: list['sys_id'],
|
|
92
|
+
view,
|
|
93
|
+
elements,
|
|
94
|
+
table: list['name'],
|
|
95
|
+
},
|
|
96
|
+
xml.filePath,
|
|
97
|
+
'list',
|
|
98
|
+
isDelete ? 'DELETE' : list['@_action']
|
|
99
|
+
)
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
composers: {
|
|
103
|
+
entity: {
|
|
104
|
+
list(entity, context) {
|
|
105
|
+
const node = entity.getNode()
|
|
106
|
+
const guid = entity.getGuid()
|
|
107
|
+
const data = entity.getValue()
|
|
108
|
+
const { view, columns, table } = data as List
|
|
109
|
+
|
|
110
|
+
const viewInfo: View = {
|
|
111
|
+
id:
|
|
112
|
+
view.$id === DEFAULT_VIEW
|
|
113
|
+
? view.$id
|
|
114
|
+
: context.keys.registerExplicitId('sys_ui_view', view.$id as unknown as string),
|
|
115
|
+
name: view.data.name,
|
|
116
|
+
title: view.data.title,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
kind: 'list',
|
|
121
|
+
node,
|
|
122
|
+
guid: getListUpdateName(viewInfo, table),
|
|
123
|
+
data: {
|
|
124
|
+
id: guid,
|
|
125
|
+
table,
|
|
126
|
+
view: viewInfo,
|
|
127
|
+
elements: columns,
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
xml: {
|
|
133
|
+
list(xml) {
|
|
134
|
+
const { sys_id, view, elements, table } = xml.data as TransformData
|
|
135
|
+
return {
|
|
136
|
+
action: xml.action,
|
|
137
|
+
kind: xml.kind,
|
|
138
|
+
guid: xml.data['updateName'] as string,
|
|
139
|
+
data: {
|
|
140
|
+
id: sys_id,
|
|
141
|
+
table,
|
|
142
|
+
view,
|
|
143
|
+
elements,
|
|
144
|
+
},
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
transformers: {
|
|
150
|
+
list: {
|
|
151
|
+
CallExpression(document, context) {
|
|
152
|
+
const expressionName = getCallExpressionName(document.node)
|
|
153
|
+
if (expressionName !== List.name) {
|
|
154
|
+
return false
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (document.action === 'DELETE') {
|
|
158
|
+
removeNode(document.node)
|
|
159
|
+
return true
|
|
160
|
+
}
|
|
161
|
+
if (document.action !== 'INSERT_OR_UPDATE') {
|
|
162
|
+
return false
|
|
163
|
+
}
|
|
164
|
+
const [listArgument] = document.node.getArguments()
|
|
165
|
+
if (!Node.isObjectLiteralExpression(listArgument)) {
|
|
166
|
+
return false
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const { elements, view, table } = document.xmlData as TransformData
|
|
170
|
+
updateView(context, listArgument, view)
|
|
171
|
+
|
|
172
|
+
//create the table reference for now, user will need to fix to proper import
|
|
173
|
+
const tableProperty = getOrCreatePropertyAssignment(listArgument, 'table', '')
|
|
174
|
+
setPropertyAssignmentValue(tableProperty, table)
|
|
175
|
+
|
|
176
|
+
const arrayElements = toArray(elements)
|
|
177
|
+
|
|
178
|
+
//update the columns
|
|
179
|
+
const columnsProperty = getOrCreatePropertyAssignment(listArgument, 'columns', '[]')
|
|
180
|
+
const columns = arrayElements.sort((a, b) => (a['position'] as number) - (b['position'] as number))
|
|
181
|
+
setColumnsList(columnsProperty, columns)
|
|
182
|
+
|
|
183
|
+
return true
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
generators: {
|
|
188
|
+
list(document, context) {
|
|
189
|
+
const { id } = document.data as any
|
|
190
|
+
return linkDocument(
|
|
191
|
+
document,
|
|
192
|
+
generateCallExpressionExportForDocument(
|
|
193
|
+
context,
|
|
194
|
+
{
|
|
195
|
+
sourceFile: getOrCreateEntitySourceFile(context, getSysUpdateName(document, 'sys_ui_list')),
|
|
196
|
+
moduleSpecifier: '@servicenow/sdk/core',
|
|
197
|
+
},
|
|
198
|
+
List,
|
|
199
|
+
{ $id: id }
|
|
200
|
+
).getExpressionIfKindOrThrow(SyntaxKind.CallExpression)
|
|
201
|
+
)
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
serializers: {
|
|
205
|
+
list(document, context) {
|
|
206
|
+
const {
|
|
207
|
+
id: listId,
|
|
208
|
+
elements: columns,
|
|
209
|
+
table,
|
|
210
|
+
view,
|
|
211
|
+
} = document.data as {
|
|
212
|
+
id: string
|
|
213
|
+
elements: Array<any>
|
|
214
|
+
table: string
|
|
215
|
+
view: View
|
|
216
|
+
}
|
|
217
|
+
const xmlBuilder = unloadBuilder(context)
|
|
218
|
+
/**
|
|
219
|
+
* Structure that needs to be built for sys_ui_list
|
|
220
|
+
* <sys_ui_list>
|
|
221
|
+
* <sys_ui_list_element>
|
|
222
|
+
* <sys_id/>
|
|
223
|
+
* </sys_ui_list_element>
|
|
224
|
+
* <sys_ui_list>
|
|
225
|
+
* <sys_id/>
|
|
226
|
+
* <view/>
|
|
227
|
+
* </sys_ui_list>
|
|
228
|
+
* </sys_ui_list>
|
|
229
|
+
*/
|
|
230
|
+
|
|
231
|
+
const listBuilder = xmlBuilder.xml.addJsonObj('sys_ui_list', undefined, {
|
|
232
|
+
table: table,
|
|
233
|
+
view: view.id === DEFAULT_VIEW ? '' : view.name,
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
columns.forEach((column, index) => {
|
|
237
|
+
let elementProperties = column
|
|
238
|
+
|
|
239
|
+
if (typeof column === 'string') {
|
|
240
|
+
elementProperties = {
|
|
241
|
+
element: column,
|
|
242
|
+
position: index,
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (elementProperties.position === undefined) {
|
|
247
|
+
elementProperties.position = index
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const childNode = recordXml(
|
|
251
|
+
listBuilder,
|
|
252
|
+
'sys_ui_list_element',
|
|
253
|
+
context.keys.registerCompositeId('sys_ui_list_element', {
|
|
254
|
+
list: listId,
|
|
255
|
+
element: elementProperties.element,
|
|
256
|
+
})
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
childNode.field('list_id', listId, {
|
|
260
|
+
display_value: table,
|
|
261
|
+
view: view.id,
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
Object.entries(elementProperties)
|
|
265
|
+
.filter(([, v]) => typeof v !== 'undefined')
|
|
266
|
+
.forEach(([n, v]) => childNode.field(n, v))
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
const sysUIList = recordXml(listBuilder, 'sys_ui_list', listId)
|
|
270
|
+
sysUIList.addSysScope(context)
|
|
271
|
+
sysUIList.field('view', view.id, {
|
|
272
|
+
display_value: view.title,
|
|
273
|
+
name: view.name,
|
|
274
|
+
})
|
|
275
|
+
sysUIList.field('name', table)
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
name: `${document.guid}.xml`,
|
|
279
|
+
directory: 'update',
|
|
280
|
+
content: xmlBuilder.end(),
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
/*
|
|
287
|
+
* Update the view property of the list argument
|
|
288
|
+
* If the view is the default view, write view as a reference from the core package
|
|
289
|
+
* If the view is a record, look for a record entity and write the view as a reference
|
|
290
|
+
*
|
|
291
|
+
* **Note:** View Cannot be updated using list layout on the instance,
|
|
292
|
+
* if the view is updated directly from sys_ui_list table, then update name changes and a new List entity is created
|
|
293
|
+
*
|
|
294
|
+
*/
|
|
295
|
+
const updateView = (context, listArgument, view) => {
|
|
296
|
+
const viewAssignment = getPropertyAssignment(listArgument, 'view')
|
|
297
|
+
if (viewAssignment) {
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
const viewRecord = context.getDocument(view.id)
|
|
301
|
+
|
|
302
|
+
if (view.id === DEFAULT_VIEW) {
|
|
303
|
+
writePropertyAsReference(listArgument, 'view', '', view.name)
|
|
304
|
+
} else if (viewRecord) {
|
|
305
|
+
const nodeSource = listArgument.getSourceFile()
|
|
306
|
+
const viewNode = viewRecord.node
|
|
307
|
+
const viewPath = getImportPath(nodeSource.getFilePath(), viewNode.getSourceFile().getFilePath())
|
|
308
|
+
|
|
309
|
+
if (!viewPath) {
|
|
310
|
+
const identifier = getIdentifier(viewNode)
|
|
311
|
+
if (identifier) {
|
|
312
|
+
listArgument.addPropertyAssignment({ name: 'view', initializer: identifier })
|
|
313
|
+
return
|
|
314
|
+
}
|
|
315
|
+
context.logger.warn(
|
|
316
|
+
`Could not find identifier for view ${view.name}, consider adding one to use as a reference`
|
|
317
|
+
)
|
|
318
|
+
listArgument.addPropertyAssignment({ name: 'view', initializer: view.name })
|
|
319
|
+
return
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// If the view record is not in the same file, add a reference to the view record
|
|
323
|
+
const viewExport = getExportTypeAndName(viewNode)
|
|
324
|
+
|
|
325
|
+
if (!viewExport.exported) {
|
|
326
|
+
context.logger.warn(
|
|
327
|
+
`View record is defined in ${path.normalize(viewNode.getSourceFile().getFilePath())} and is not exported`
|
|
328
|
+
)
|
|
329
|
+
listArgument.addPropertyAssignment({ name: 'view', initializer: view.name })
|
|
330
|
+
return
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Add a reference to the view record and add an import statement
|
|
334
|
+
if (viewExport.type === 'Default') {
|
|
335
|
+
listArgument.addPropertyAssignment({ name: 'view', initializer: view.name })
|
|
336
|
+
addDefaultImportIfAbsent(nodeSource, viewPath, view.name)
|
|
337
|
+
} else {
|
|
338
|
+
listArgument.addPropertyAssignment({ name: 'view', initializer: viewExport.identifier })
|
|
339
|
+
addNamedImportIfAbsent(context, nodeSource, viewPath, viewExport.identifier)
|
|
340
|
+
}
|
|
341
|
+
} else {
|
|
342
|
+
listArgument.addPropertyAssignment({ name: 'view', initializer: view.name })
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
type ExportsInfo =
|
|
347
|
+
| { exported: false; identifier?: string }
|
|
348
|
+
| { exported: true; identifier: string; type: 'Named' }
|
|
349
|
+
| { exported: true; type: 'Default' }
|
|
350
|
+
|
|
351
|
+
const getExportTypeAndName = (sourceNode: CallExpression): ExportsInfo => {
|
|
352
|
+
// const defaultExports = sourceNode.getSourceFile().getExportSymbols()
|
|
353
|
+
const parentNode = sourceNode.getParent()
|
|
354
|
+
|
|
355
|
+
// export declarations are blocked by fluent-diagnostics
|
|
356
|
+
switch (parentNode?.getKind()) {
|
|
357
|
+
case SyntaxKind.ExportAssignment:
|
|
358
|
+
return { exported: true, type: 'Default' }
|
|
359
|
+
case SyntaxKind.VariableDeclaration: {
|
|
360
|
+
const identifier = getIdentifier(parentNode as VariableDeclaration)!
|
|
361
|
+
|
|
362
|
+
const variableStmt = parentNode.getParentIfKind(SyntaxKind.VariableStatement)
|
|
363
|
+
const exportKeyword = variableStmt?.getFirstChildByKind(SyntaxKind.ExportKeyword)
|
|
364
|
+
|
|
365
|
+
if (exportKeyword) {
|
|
366
|
+
return { exported: true, type: 'Named', identifier }
|
|
367
|
+
}
|
|
368
|
+
return { exported: false, identifier }
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
case SyntaxKind.ExpressionStatement:
|
|
372
|
+
default:
|
|
373
|
+
return { exported: false }
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const getIdentifier = (sourceNode: CallExpression | VariableDeclaration): string | undefined => {
|
|
378
|
+
const variableDeclaration =
|
|
379
|
+
sourceNode.getKind() === SyntaxKind.CallExpression
|
|
380
|
+
? sourceNode.getParentIfKind(SyntaxKind.VariableDeclaration)
|
|
381
|
+
: sourceNode
|
|
382
|
+
|
|
383
|
+
return variableDeclaration?.getFirstChildByKind(SyntaxKind.Identifier)?.getText()
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const getImportPath = (listSourcePath, viewSourcePath): string | undefined => {
|
|
387
|
+
if (listSourcePath === viewSourcePath) {
|
|
388
|
+
return
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const viewFilePath = path.parse(viewSourcePath)
|
|
392
|
+
const listFilePath = path.parse(listSourcePath)
|
|
393
|
+
const relativePath = path.posix.join(path.relative(listFilePath.dir, viewFilePath.dir), viewFilePath.name)
|
|
394
|
+
// relativePath = relativePath.replace(path.extname(relativePath), '')
|
|
395
|
+
return relativePath.startsWith('.') ? relativePath : `./${relativePath}`
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const setColumnsList = (columnsProperty: PropertyAssignment, elements: SysUIListElementXml) => {
|
|
399
|
+
const [array] = columnsProperty.getChildrenOfKind(SyntaxKind.ArrayLiteralExpression)
|
|
400
|
+
let serializeValue: string = '[]'
|
|
401
|
+
if (array) {
|
|
402
|
+
const elementSyntaxList = array.getChildAtIndexIfKind(1, SyntaxKind.SyntaxList)
|
|
403
|
+
|
|
404
|
+
//If the columns are defined as objects or need to be expressed that way due to additional properties set on instance
|
|
405
|
+
if (
|
|
406
|
+
!!elementSyntaxList?.getChildrenOfKind(SyntaxKind.ObjectLiteralExpression).length ||
|
|
407
|
+
columnsNeedObjectLiterals(elements)
|
|
408
|
+
) {
|
|
409
|
+
const newElements = elements.map((element, index) => {
|
|
410
|
+
let newValue: Record<string, unknown>
|
|
411
|
+
|
|
412
|
+
if (typeof element === 'string') {
|
|
413
|
+
newValue = element
|
|
414
|
+
} else {
|
|
415
|
+
newValue = {
|
|
416
|
+
element: element['element'],
|
|
417
|
+
position: element['position'] ?? index,
|
|
418
|
+
}
|
|
419
|
+
if (element['average_value']) {
|
|
420
|
+
newValue['average_value'] = true
|
|
421
|
+
}
|
|
422
|
+
if (element['max_value']) {
|
|
423
|
+
newValue['max_value'] = true
|
|
424
|
+
}
|
|
425
|
+
if (element['min_value']) {
|
|
426
|
+
newValue['min_value'] = true
|
|
427
|
+
}
|
|
428
|
+
if (element['sum']) {
|
|
429
|
+
newValue['sum'] = true
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return newValue
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
serializeValue = JSON.stringify(newElements)
|
|
437
|
+
} else {
|
|
438
|
+
serializeValue = JSON.stringify(elements.map((e) => e['element']))
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
columnsProperty?.replaceWithText(`columns: ${serializeValue}`)
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const columnsNeedObjectLiterals = (elements: SysUIListElementXml) => {
|
|
445
|
+
return elements.some((element) => {
|
|
446
|
+
return Object.keys(element)
|
|
447
|
+
.filter((key) => !key.startsWith('sys_') && !key.startsWith('@_'))
|
|
448
|
+
.some((key) => {
|
|
449
|
+
switch (key) {
|
|
450
|
+
case 'position':
|
|
451
|
+
case 'list_id':
|
|
452
|
+
case 'element':
|
|
453
|
+
return false
|
|
454
|
+
case 'average_value':
|
|
455
|
+
case 'max_value':
|
|
456
|
+
case 'sum':
|
|
457
|
+
case 'min_value':
|
|
458
|
+
return !!element[key]
|
|
459
|
+
default: //Non default properties are unknown so just return true
|
|
460
|
+
return true
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
})
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const xmlElementToObject = (element: PrimitiveData) => {
|
|
467
|
+
return Object.entries(element).reduce((out, [k, v]) => {
|
|
468
|
+
out[k] = typeof v === 'string' ? v : v ? v['#text'] : ''
|
|
469
|
+
return out
|
|
470
|
+
}, {})
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
const getListUpdateName = (view: View, table: string) => {
|
|
474
|
+
const viewName = view.title === DEFAULT_VIEW ? 'null' : view.name
|
|
475
|
+
return `sys_ui_list_${table}_${viewName}` //This name matches the generated
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
const SysUIListXmlSchema = z.object({
|
|
479
|
+
sys_ui_list: z.object({
|
|
480
|
+
'@_action': z.union([z.literal('DELETE'), z.literal('INSERT_OR_UPDATE')]).optional(),
|
|
481
|
+
'@_table': z.string(),
|
|
482
|
+
'@_view': z.string(),
|
|
483
|
+
sys_ui_list: RecordXmlSchema,
|
|
484
|
+
sys_ui_list_element: z.union([z.array(RecordXmlSchema), RecordXmlSchema]),
|
|
485
|
+
}),
|
|
486
|
+
sys_metadata_delete: z
|
|
487
|
+
.object({
|
|
488
|
+
sys_update_name: z.object({
|
|
489
|
+
'#text': z.string(),
|
|
490
|
+
}),
|
|
491
|
+
})
|
|
492
|
+
.optional(),
|
|
493
|
+
})
|
|
494
|
+
|
|
495
|
+
const toArray = (value: unknown) => (Array.isArray(value) ? value : [value])
|
|
496
|
+
|
|
497
|
+
type SysUIListElementXml = z.infer<typeof RecordXmlSchema>[]
|