@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.
Files changed (166) hide show
  1. package/dist/AttachmentPlugin.d.ts +253 -0
  2. package/dist/AttachmentPlugin.js +216 -0
  3. package/dist/AttachmentPlugin.js.map +1 -0
  4. package/dist/BusinessRulePlugin.d.ts +56 -0
  5. package/dist/BusinessRulePlugin.js +171 -0
  6. package/dist/BusinessRulePlugin.js.map +1 -0
  7. package/dist/CrossScopePrivilegePlugin.d.ts +22 -0
  8. package/dist/CrossScopePrivilegePlugin.js +42 -0
  9. package/dist/CrossScopePrivilegePlugin.js.map +1 -0
  10. package/dist/DefaultPlugin.d.ts +71 -0
  11. package/dist/DefaultPlugin.js +238 -0
  12. package/dist/DefaultPlugin.js.map +1 -0
  13. package/dist/IdPlugin.d.ts +17 -0
  14. package/dist/IdPlugin.js +45 -0
  15. package/dist/IdPlugin.js.map +1 -0
  16. package/dist/ListPlugin.d.ts +91 -0
  17. package/dist/ListPlugin.js +398 -0
  18. package/dist/ListPlugin.js.map +1 -0
  19. package/dist/PropertyPlugin.d.ts +122 -0
  20. package/dist/PropertyPlugin.js +165 -0
  21. package/dist/PropertyPlugin.js.map +1 -0
  22. package/dist/ScriptTemplatePlugin.d.ts +31 -0
  23. package/dist/ScriptTemplatePlugin.js +208 -0
  24. package/dist/ScriptTemplatePlugin.js.map +1 -0
  25. package/dist/UserPreferencePlugin.d.ts +16 -0
  26. package/dist/UserPreferencePlugin.js +30 -0
  27. package/dist/UserPreferencePlugin.js.map +1 -0
  28. package/dist/aclAndRole/AclPlugin.d.ts +117 -0
  29. package/dist/aclAndRole/AclPlugin.js +285 -0
  30. package/dist/aclAndRole/AclPlugin.js.map +1 -0
  31. package/dist/aclAndRole/RolePlugin.d.ts +58 -0
  32. package/dist/aclAndRole/RolePlugin.js +152 -0
  33. package/dist/aclAndRole/RolePlugin.js.map +1 -0
  34. package/dist/aclAndRole/Util.d.ts +3 -0
  35. package/dist/aclAndRole/Util.js +106 -0
  36. package/dist/aclAndRole/Util.js.map +1 -0
  37. package/dist/app/ApplicationMenuPlugin.d.ts +32 -0
  38. package/dist/app/ApplicationMenuPlugin.js +106 -0
  39. package/dist/app/ApplicationMenuPlugin.js.map +1 -0
  40. package/dist/atf/ATFComposer.d.ts +492 -0
  41. package/dist/atf/ATFComposer.js +2717 -0
  42. package/dist/atf/ATFComposer.js.map +1 -0
  43. package/dist/atf/TestPlugin.d.ts +31 -0
  44. package/dist/atf/TestPlugin.js +95 -0
  45. package/dist/atf/TestPlugin.js.map +1 -0
  46. package/dist/atf/index.d.ts +1 -0
  47. package/dist/atf/index.js +9 -0
  48. package/dist/atf/index.js.map +1 -0
  49. package/dist/db/ColumnPlugins.d.ts +278 -0
  50. package/dist/db/ColumnPlugins.js +112 -0
  51. package/dist/db/ColumnPlugins.js.map +1 -0
  52. package/dist/db/RecordPlugin.d.ts +208 -0
  53. package/dist/db/RecordPlugin.js +287 -0
  54. package/dist/db/RecordPlugin.js.map +1 -0
  55. package/dist/db/TablePlugin.d.ts +742 -0
  56. package/dist/db/TablePlugin.js +1249 -0
  57. package/dist/db/TablePlugin.js.map +1 -0
  58. package/dist/db/index.d.ts +3 -0
  59. package/dist/db/index.js +27 -0
  60. package/dist/db/index.js.map +1 -0
  61. package/dist/index.d.ts +16 -0
  62. package/dist/index.js +51 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/scriptedRESTAPI/RESTDeserializationUtils.d.ts +12 -0
  65. package/dist/scriptedRESTAPI/RESTDeserializationUtils.js +371 -0
  66. package/dist/scriptedRESTAPI/RESTDeserializationUtils.js.map +1 -0
  67. package/dist/scriptedRESTAPI/RESTSerializationUtils.d.ts +15 -0
  68. package/dist/scriptedRESTAPI/RESTSerializationUtils.js +177 -0
  69. package/dist/scriptedRESTAPI/RESTSerializationUtils.js.map +1 -0
  70. package/dist/scriptedRESTAPI/RestApiPlugin.d.ts +144 -0
  71. package/dist/scriptedRESTAPI/RestApiPlugin.js +318 -0
  72. package/dist/scriptedRESTAPI/RestApiPlugin.js.map +1 -0
  73. package/dist/scriptedRESTAPI/RestSchemaUtils.d.ts +190 -0
  74. package/dist/scriptedRESTAPI/RestSchemaUtils.js +53 -0
  75. package/dist/scriptedRESTAPI/RestSchemaUtils.js.map +1 -0
  76. package/dist/scriptedRESTAPI/RestUtils.d.ts +75 -0
  77. package/dist/scriptedRESTAPI/RestUtils.js +469 -0
  78. package/dist/scriptedRESTAPI/RestUtils.js.map +1 -0
  79. package/dist/scripts/ClientScriptPlugin.d.ts +43 -0
  80. package/dist/scripts/ClientScriptPlugin.js +190 -0
  81. package/dist/scripts/ClientScriptPlugin.js.map +1 -0
  82. package/dist/scripts/scriptUtils.d.ts +15 -0
  83. package/dist/scripts/scriptUtils.js +83 -0
  84. package/dist/scripts/scriptUtils.js.map +1 -0
  85. package/dist/uxf/ExperiencePlugin.d.ts +22 -0
  86. package/dist/uxf/ExperiencePlugin.js +55 -0
  87. package/dist/uxf/ExperiencePlugin.js.map +1 -0
  88. package/dist/uxf/RoutesPlugin.d.ts +22 -0
  89. package/dist/uxf/RoutesPlugin.js +176 -0
  90. package/dist/uxf/RoutesPlugin.js.map +1 -0
  91. package/dist/uxf/UxfFormulaParser/cleanUxValue.d.ts +4 -0
  92. package/dist/uxf/UxfFormulaParser/cleanUxValue.js +65 -0
  93. package/dist/uxf/UxfFormulaParser/cleanUxValue.js.map +1 -0
  94. package/dist/uxf/UxfFormulaParser/grammerParser/api.d.ts +189 -0
  95. package/dist/uxf/UxfFormulaParser/grammerParser/api.js +158 -0
  96. package/dist/uxf/UxfFormulaParser/grammerParser/api.js.map +1 -0
  97. package/dist/uxf/UxfFormulaParser/grammerParser/clientTransformMap.d.ts +13 -0
  98. package/dist/uxf/UxfFormulaParser/grammerParser/clientTransformMap.js +604 -0
  99. package/dist/uxf/UxfFormulaParser/grammerParser/clientTransformMap.js.map +1 -0
  100. package/dist/uxf/UxfFormulaParser/grammerParser/grammarParser.d.ts +12 -0
  101. package/dist/uxf/UxfFormulaParser/grammerParser/grammarParser.js +551 -0
  102. package/dist/uxf/UxfFormulaParser/grammerParser/grammarParser.js.map +1 -0
  103. package/dist/uxf/UxfFormulaParser/grammerParser/spanHelpers.d.ts +31 -0
  104. package/dist/uxf/UxfFormulaParser/grammerParser/spanHelpers.js +64 -0
  105. package/dist/uxf/UxfFormulaParser/grammerParser/spanHelpers.js.map +1 -0
  106. package/dist/uxf/UxfFormulaParser/index.d.ts +3 -0
  107. package/dist/uxf/UxfFormulaParser/index.js +11 -0
  108. package/dist/uxf/UxfFormulaParser/index.js.map +1 -0
  109. package/dist/uxf/UxfFormulaParser/parser.d.ts +8 -0
  110. package/dist/uxf/UxfFormulaParser/parser.js +87 -0
  111. package/dist/uxf/UxfFormulaParser/parser.js.map +1 -0
  112. package/dist/uxf/UxfFormulaParser/utils/getErrorMsg.d.ts +8 -0
  113. package/dist/uxf/UxfFormulaParser/utils/getErrorMsg.js +17 -0
  114. package/dist/uxf/UxfFormulaParser/utils/getErrorMsg.js.map +1 -0
  115. package/dist/uxf/constants.d.ts +2 -0
  116. package/dist/uxf/constants.js +8 -0
  117. package/dist/uxf/constants.js.map +1 -0
  118. package/dist/uxf/index.d.ts +2 -0
  119. package/dist/uxf/index.js +11 -0
  120. package/dist/uxf/index.js.map +1 -0
  121. package/dist/uxf/tectonicIdGenerator.d.ts +12 -0
  122. package/dist/uxf/tectonicIdGenerator.js +102 -0
  123. package/dist/uxf/tectonicIdGenerator.js.map +1 -0
  124. package/license +9 -0
  125. package/package.json +42 -0
  126. package/src/AttachmentPlugin.ts +262 -0
  127. package/src/BusinessRulePlugin.ts +251 -0
  128. package/src/CrossScopePrivilegePlugin.ts +54 -0
  129. package/src/DefaultPlugin.ts +272 -0
  130. package/src/IdPlugin.ts +47 -0
  131. package/src/ListPlugin.ts +497 -0
  132. package/src/PropertyPlugin.ts +218 -0
  133. package/src/ScriptTemplatePlugin.ts +223 -0
  134. package/src/UserPreferencePlugin.ts +36 -0
  135. package/src/aclAndRole/AclPlugin.ts +410 -0
  136. package/src/aclAndRole/RolePlugin.ts +225 -0
  137. package/src/aclAndRole/Util.ts +104 -0
  138. package/src/app/ApplicationMenuPlugin.ts +158 -0
  139. package/src/atf/ATFComposer.ts +3356 -0
  140. package/src/atf/TestPlugin.ts +119 -0
  141. package/src/atf/index.ts +1 -0
  142. package/src/db/ColumnPlugins.ts +117 -0
  143. package/src/db/RecordPlugin.ts +391 -0
  144. package/src/db/TablePlugin.ts +1581 -0
  145. package/src/db/index.ts +3 -0
  146. package/src/index.ts +16 -0
  147. package/src/scriptedRESTAPI/RESTDeserializationUtils.ts +410 -0
  148. package/src/scriptedRESTAPI/RESTSerializationUtils.ts +227 -0
  149. package/src/scriptedRESTAPI/RestApiPlugin.ts +438 -0
  150. package/src/scriptedRESTAPI/RestSchemaUtils.ts +72 -0
  151. package/src/scriptedRESTAPI/RestUtils.ts +507 -0
  152. package/src/scripts/ClientScriptPlugin.ts +251 -0
  153. package/src/scripts/scriptUtils.ts +81 -0
  154. package/src/uxf/ExperiencePlugin.ts +64 -0
  155. package/src/uxf/RoutesPlugin.ts +215 -0
  156. package/src/uxf/UxfFormulaParser/cleanUxValue.ts +73 -0
  157. package/src/uxf/UxfFormulaParser/grammerParser/api.js +166 -0
  158. package/src/uxf/UxfFormulaParser/grammerParser/clientTransformMap.js +606 -0
  159. package/src/uxf/UxfFormulaParser/grammerParser/grammarParser.js +551 -0
  160. package/src/uxf/UxfFormulaParser/grammerParser/spanHelpers.js +65 -0
  161. package/src/uxf/UxfFormulaParser/index.ts +4 -0
  162. package/src/uxf/UxfFormulaParser/parser.ts +64 -0
  163. package/src/uxf/UxfFormulaParser/utils/getErrorMsg.ts +13 -0
  164. package/src/uxf/constants.ts +4 -0
  165. package/src/uxf/index.ts +2 -0
  166. package/src/uxf/tectonicIdGenerator.ts +81 -0
@@ -0,0 +1,438 @@
1
+ import { RestApi, RestApiConfig, RestApiSchema, Version } from '@servicenow/sdk-core/runtime/rest'
2
+ import { Record, RecordWithLegacyId } from '@servicenow/sdk-core/runtime/db'
3
+ import {
4
+ linkDocument,
5
+ Context,
6
+ Plugin,
7
+ Document,
8
+ extractCallExpression,
9
+ getCallExpressionName,
10
+ generateCallExpressionExportForDocument,
11
+ getOrCreateEntitySourceFile,
12
+ getSysUpdateName,
13
+ EntityData,
14
+ ObjectData,
15
+ } from '@servicenow/sdk-build-core'
16
+ import { RecordPlugin } from '../db/RecordPlugin'
17
+ import { buildScriptImport, scriptInfo, type ScriptInfo } from '../scripts/scriptUtils'
18
+ import {
19
+ EnforceAcl,
20
+ mergeACLIds,
21
+ generateVersionRecords,
22
+ generateRoutesAndRouteAttrRecords,
23
+ } from './RESTSerializationUtils'
24
+ import * as ts from 'ts-morph'
25
+ import {
26
+ transformDefinition,
27
+ transformRestAttrs,
28
+ transformRouteAttrs,
29
+ transformRouteAttrsMap,
30
+ transformRoutes,
31
+ } from './RESTDeserializationUtils'
32
+ import { RestRouteHeaderMap, RestRouteQueryMap } from './RestSchemaUtils'
33
+ import {
34
+ getRestDocumentMap,
35
+ getRouteAttrResult,
36
+ getRouteAttrMapResult,
37
+ getRouteAttrWithRecordNodeResult,
38
+ getRouteAttrWithRestNodeResult,
39
+ getRouteAttrMapWithRecordNodeResult,
40
+ getRouteAttrMapWithRestNodeResult,
41
+ handleAndReturnResult,
42
+ createRecordCall,
43
+ restTables,
44
+ unHandledIds,
45
+ completelyUnassociatedParamIds,
46
+ potentialRecordCallRouteParams,
47
+ } from './RestUtils'
48
+ import * as z from 'zod'
49
+ import { Diagnostic } from '@servicenow/sdk-project'
50
+
51
+ const methodsAllowedToOverrideRequests = ['PUT', 'PATCH', 'POST']
52
+ const parseAcls = (enforce_acl: EnforceAcl, context: Context) =>
53
+ enforce_acl.map((acl) => (typeof acl === 'string' ? acl : context.keys.registerExplicitId(acl.table, acl.$id)))
54
+
55
+ function restApiAsRecord<I extends number, V extends Version<I>>(config: RestApiConfig<I, V>) {
56
+ const api = RestApiSchema.parse(config)
57
+ return Record({
58
+ table: 'sys_ws_definition',
59
+ $id: api.$id,
60
+ data: {
61
+ active: api.active,
62
+ name: api.name,
63
+ consumes: api.consumes,
64
+ consumes_customized: api.consumes === RestApiSchema.shape.consumes._def.defaultValue() ? false : true,
65
+ produces: api.produces,
66
+ produces_customized: api.produces === RestApiSchema.shape.produces._def.defaultValue() ? false : true,
67
+ default_version: '',
68
+ doc_link: api.doc_link,
69
+ is_versioned: false,
70
+ service_id: api.service_id,
71
+ short_description: api.short_description,
72
+ base_uri: '',
73
+ namespace: '',
74
+ enforce_acl: api.enforce_acl as any,
75
+ ...(api.policy && { sys_policy: api.policy }),
76
+ },
77
+ })
78
+ }
79
+
80
+ export default Plugin({
81
+ name: 'RestApi',
82
+ ownedTables: {
83
+ sys_ws_definition: { diagnosticLevel: Diagnostic.Level.Warn },
84
+ sys_ws_version: { diagnosticLevel: Diagnostic.Level.Warn },
85
+ sys_ws_operation: { diagnosticLevel: Diagnostic.Level.Warn },
86
+ },
87
+ extractors: {
88
+ entity: {
89
+ CallExpression: (node, context) => {
90
+ const result = extractCallExpression(RestApi, 'restApi', node, context, (restApi) =>
91
+ context.registerExplicitId('sys_ws_definition', restApi.$id as string)
92
+ )
93
+
94
+ if (!result.handled || !(0 in result.data)) {
95
+ return result
96
+ }
97
+
98
+ const restAPIEntity = result.data[0]
99
+ const entityData = RestApiSchema.parse(restAPIEntity.getValue())
100
+ const { routes, enforce_acl, consumes, produces } = entityData
101
+ for (const route of routes) {
102
+ const { enforce_acl } = route
103
+ const rawOperationScript = route.script as unknown as ScriptInfo | string
104
+ route.name = route.name ? route.name : route.path
105
+
106
+ if (typeof rawOperationScript !== 'string') {
107
+ const { filePath, functionName, isDefault } = rawOperationScript
108
+ route.script = buildScriptImport(
109
+ filePath,
110
+ functionName,
111
+ isDefault,
112
+ context,
113
+ (funcName: string) => `${funcName}(request, response)\n`
114
+ )
115
+ }
116
+
117
+ /** allow users to override consumes for allowed http methods*/
118
+ if (
119
+ route.consumes &&
120
+ route.consumes !== consumes &&
121
+ !methodsAllowedToOverrideRequests.includes(route.method)
122
+ ) {
123
+ throw Error(`Cannot override consumer type for ${route.method} method`)
124
+ }
125
+
126
+ route.consumes = route.consumes ? route.consumes : consumes
127
+ route.produces = route.produces ? route.produces : produces
128
+ route.enforce_acl = parseAcls(enforce_acl, context)
129
+ }
130
+
131
+ return {
132
+ handled: true,
133
+ diagnostics: result.diagnostics,
134
+ data: [
135
+ new EntityData(
136
+ restAPIEntity.getKind(),
137
+ restAPIEntity.getGuid(),
138
+ ObjectData.fromObjectValue(
139
+ {
140
+ ...entityData,
141
+ enforce_acl: parseAcls(enforce_acl, context),
142
+ },
143
+ restAPIEntity.getNode()
144
+ ),
145
+ restAPIEntity.getNode()
146
+ ),
147
+ ],
148
+ }
149
+ },
150
+ },
151
+ raw: {
152
+ FunctionDeclaration(node, context) {
153
+ const info = scriptInfo(node, context, RestApi.name)
154
+ if (!info) {
155
+ return { handled: false }
156
+ }
157
+
158
+ return { handled: true, diagnostics: [], data: [info] }
159
+ },
160
+
161
+ FunctionExpression(node, context) {
162
+ const info = scriptInfo(node, context, RestApi.name)
163
+ if (!info) {
164
+ return { handled: false }
165
+ }
166
+
167
+ return { handled: true, diagnostics: [], data: [info] }
168
+ },
169
+ },
170
+ },
171
+ composers: {
172
+ entity: {
173
+ restApi(entity, context) {
174
+ const restEntity = entity.getValue()
175
+ const parsedEntity = RestApiSchema.safeParse(restEntity)
176
+ if (!parsedEntity.success) {
177
+ return
178
+ }
179
+
180
+ const { routes, versions, enforce_acl } = parsedEntity.data
181
+ const defaultVersions = versions.filter((version) => version.is_default)
182
+ if (defaultVersions.length > 1) {
183
+ throw Error(`Multiple versions cannot be set to default.`)
184
+ }
185
+
186
+ const {
187
+ app: {
188
+ config: { scope },
189
+ },
190
+ } = context
191
+ const restRecord = restApiAsRecord(restEntity as any) as RecordWithLegacyId<'sys_ws_definition'>
192
+ const apiData = { ...restRecord.data }
193
+
194
+ apiData.base_uri = `/api/${scope}/${apiData.service_id}`
195
+ apiData.namespace = scope
196
+ apiData.default_version =
197
+ defaultVersions.length > 0 ? `v${defaultVersions[0]!.version}` : 'No active default version'
198
+ apiData.enforce_acl = mergeACLIds(enforce_acl) as any
199
+ apiData.is_versioned = versions.length > 0 ? true : false
200
+
201
+ /** generates sys_ws_definition record */
202
+ const updatedRestRecord = Record({
203
+ table: 'sys_ws_definition',
204
+ $id: entity.getGuid(),
205
+ data: apiData,
206
+ })
207
+
208
+ /** generates the sys_ws_version record */
209
+ const versionRecordsAndMap = generateVersionRecords(
210
+ context,
211
+ apiData.default_version,
212
+ versions,
213
+ updatedRestRecord
214
+ )
215
+
216
+ /** generates the sys_ws_operation, sys_ws_header, sys_ws_header_map, sys_ws_query_paramter, sys_ws_query_parameter_map records */
217
+ const routesAndRouteAttrRecords = generateRoutesAndRouteAttrRecords(
218
+ context,
219
+ restRecord.$id,
220
+ routes,
221
+ apiData,
222
+ updatedRestRecord,
223
+ versionRecordsAndMap.mapping
224
+ )
225
+
226
+ return context.composeEntities(
227
+ [updatedRestRecord, ...versionRecordsAndMap.records, ...routesAndRouteAttrRecords].map(
228
+ (r) =>
229
+ new EntityData(
230
+ 'record',
231
+ r.$id as string,
232
+ ObjectData.fromObjectValue(r, entity.getNode()),
233
+ entity.getNode()
234
+ )
235
+ ),
236
+ [RecordPlugin]
237
+ )
238
+ },
239
+ },
240
+ },
241
+ arrangers: {
242
+ record(document, context) {
243
+ const table = document.data!['table']
244
+ /** skipping arrangers while serializing as we don't care about the order here. */
245
+ if (!restTables.includes(table) || context.mode === 'serialize') {
246
+ return { handled: false }
247
+ }
248
+
249
+ /** generates rest document map and validates the params and their mapping records */
250
+ const restDocMap = getRestDocumentMap(context)
251
+ switch (table) {
252
+ case 'sys_ws_operation':
253
+ case 'sys_ws_version':
254
+ return {
255
+ handled: true,
256
+ result: { kind: 'record', guid: document.data!['data']['web_service_definition'] },
257
+ }
258
+ case 'sys_ws_header':
259
+ case 'sys_ws_query_parameter':
260
+ if (!document.node) {
261
+ /** handles case where the incoming xml doesn't have any node associated with it. */
262
+ return handleAndReturnResult(getRouteAttrResult(document, restDocMap), document)
263
+ } else {
264
+ const docNode = document.node as ts.CallExpression
265
+ if (getCallExpressionName(docNode) === Record.name) {
266
+ /** handles case where the incoming xml is currently associated with record call */
267
+ return handleAndReturnResult(
268
+ getRouteAttrWithRecordNodeResult(document, context, restDocMap),
269
+ document
270
+ )
271
+ } else {
272
+ /** handles case where the incoming xml is currently associated with rest call */
273
+ return handleAndReturnResult(
274
+ getRouteAttrWithRestNodeResult(document, context, restDocMap),
275
+ document
276
+ )
277
+ }
278
+ }
279
+ case 'sys_ws_header_map':
280
+ case 'sys_ws_query_parameter_map':
281
+ if (!document.node) {
282
+ /** handles case where the incoming xml doesn't have any node associated with it. */
283
+ return handleAndReturnResult(getRouteAttrMapResult(document, restDocMap), document)
284
+ } else {
285
+ const docNode = document.node as ts.CallExpression
286
+ if (getCallExpressionName(docNode) === Record.name) {
287
+ /** handles case where the incoming xml is currently associated with record call */
288
+ return handleAndReturnResult(
289
+ getRouteAttrMapWithRecordNodeResult(document, context, restDocMap),
290
+ document
291
+ )
292
+ } else {
293
+ /** handles case where the incoming xml is currently associated with rest call */
294
+ return handleAndReturnResult(
295
+ getRouteAttrMapWithRestNodeResult(document, context, restDocMap),
296
+ document
297
+ )
298
+ }
299
+ }
300
+ default:
301
+ return { handled: true, result: undefined }
302
+ }
303
+ },
304
+ },
305
+ generators: {
306
+ record(document, context, linkedDocuments) {
307
+ const table = document.data!['table']
308
+ /**
309
+ * Edge case: m2m record maps non-app rest causing you to unassociate the only associated
310
+ * param record to rest. May require creation of record call for unassociated param if not consumed
311
+ * by any
312
+ */
313
+ completelyUnassociatedParamIds.forEach((id) => {
314
+ if (potentialRecordCallRouteParams.has(id)) {
315
+ createRecordCall(id, context)
316
+ potentialRecordCallRouteParams.delete(id)
317
+ }
318
+ })
319
+ completelyUnassociatedParamIds.clear()
320
+ /** unHandledIds contains rest record ids for which we need to create record call */
321
+ if (!restTables.includes(table) || unHandledIds.includes(document.guid)) {
322
+ return undefined
323
+ }
324
+
325
+ switch (table) {
326
+ case 'sys_ws_definition':
327
+ // eslint-disable-next-line no-case-declarations
328
+ const linkedDoc = linkDocument(
329
+ document,
330
+ generateCallExpressionExportForDocument(
331
+ context,
332
+ {
333
+ sourceFile: getOrCreateEntitySourceFile(
334
+ context,
335
+ getSysUpdateName(document, 'sys_ws_definition')
336
+ ),
337
+ moduleSpecifier: '@servicenow/sdk/core',
338
+ },
339
+ RestApi,
340
+ {}
341
+ ).getExpressionIfKindOrThrow(ts.SyntaxKind.CallExpression)
342
+ )
343
+ return linkedDoc
344
+ case 'sys_ws_operation':
345
+ case 'sys_ws_version':
346
+ case 'sys_ws_header':
347
+ case 'sys_ws_query_parameter':
348
+ // eslint-disable-next-line no-case-declarations
349
+ const restDef = linkedDocuments.find(
350
+ (doc) =>
351
+ (doc.data as any).table === 'sys_ws_definition' &&
352
+ doc.guid === (document.data as any).data.web_service_definition
353
+ )
354
+ // eslint-disable-next-line no-case-declarations
355
+ const o_v_node = document.parent!.node ? document.parent!.node : restDef?.node
356
+ if (!o_v_node) {
357
+ return undefined
358
+ }
359
+ return linkDocument(document, o_v_node as ts.CallExpression<ts.ts.CallExpression>)
360
+ case 'sys_ws_header_map':
361
+ case 'sys_ws_query_parameter_map':
362
+ // eslint-disable-next-line no-case-declarations
363
+ const operationDef = linkedDocuments.find(
364
+ (doc) =>
365
+ (doc.data as any).table === 'sys_ws_operation' &&
366
+ doc.guid === (document.data as any).data.web_service_operation
367
+ )
368
+ // eslint-disable-next-line no-case-declarations
369
+ const h_q_node = document.parent?.node ? document.parent?.node : operationDef?.node
370
+ if (!h_q_node) {
371
+ return undefined
372
+ }
373
+ return linkDocument(document, h_q_node as ts.CallExpression<ts.ts.CallExpression>)
374
+ }
375
+ return undefined
376
+ },
377
+ },
378
+ transformers: {
379
+ record: {
380
+ CallExpression(document, context) {
381
+ if (!shouldHandle(document)) {
382
+ return false
383
+ }
384
+
385
+ const documentMap = context.getDocumentMap()
386
+ const table = document.data!['table']
387
+ switch (table) {
388
+ case 'sys_ws_definition':
389
+ return transformDefinition(document, context)
390
+ case 'sys_ws_version':
391
+ return transformRestAttrs(document, context)
392
+ case 'sys_ws_operation':
393
+ return transformRoutes(document, context, documentMap!)
394
+ case 'sys_ws_header':
395
+ return transformRouteAttrs(document, context, 'headers')
396
+ case 'sys_ws_query_parameter':
397
+ return transformRouteAttrs(document, context, 'parameters')
398
+ case 'sys_ws_query_parameter_map':
399
+ return transformRouteAttrsMap(
400
+ document,
401
+ context,
402
+ documentMap!,
403
+ RestRouteQueryMap,
404
+ 'parameters',
405
+ (data: z.infer<typeof RestRouteQueryMap>) => {
406
+ return {
407
+ operationId: data.web_service_operation,
408
+ attrId: data.web_service_query_parameter,
409
+ }
410
+ }
411
+ )
412
+ case 'sys_ws_header_map':
413
+ return transformRouteAttrsMap(
414
+ document,
415
+ context,
416
+ documentMap!,
417
+ RestRouteHeaderMap,
418
+ 'headers',
419
+ (data: z.infer<typeof RestRouteHeaderMap>) => {
420
+ return { operationId: data.web_service_operation, attrId: data.web_service_header }
421
+ }
422
+ )
423
+ }
424
+ return false
425
+ },
426
+ },
427
+ },
428
+ })
429
+
430
+ function shouldHandle(document: Document): boolean {
431
+ const docNode = document.node as ts.CallExpression
432
+ return !docNode.wasForgotten() &&
433
+ getCallExpressionName(docNode) === RestApi.name &&
434
+ document.data!['table'] &&
435
+ docNode.getArguments()[0]
436
+ ? true
437
+ : false
438
+ }
@@ -0,0 +1,72 @@
1
+ import {
2
+ BaseRestApiSchema,
3
+ BaseRouteSchema,
4
+ RouteAttributeSchema,
5
+ VersionSchema,
6
+ } from '@servicenow/sdk-core/runtime/rest'
7
+ import { z } from 'zod'
8
+
9
+ export const RestRouteHeaderMap = z.object({
10
+ web_service_operation: z.string(),
11
+ web_service_header: z.string(),
12
+ })
13
+
14
+ export const RestRouteQueryMap = z.object({
15
+ web_service_operation: z.string(),
16
+ web_service_query_parameter: z.string(),
17
+ })
18
+
19
+ export const RouteAttrWithOutIdSchema = RouteAttributeSchema.omit({ $id: true })
20
+
21
+ export const VersionWithOutIdSchema = VersionSchema.omit({ $id: true })
22
+
23
+ const RestDefinitionSchema = BaseRestApiSchema.omit({ $id: true }).extend({
24
+ enforce_acl: z.string().default(''),
25
+ sys_policy: z.enum(['', 'read', 'protected']).default(''),
26
+ })
27
+
28
+ export const RestDefinitionTransformer = RestDefinitionSchema.partial().transform((data) => {
29
+ const { sys_policy, enforce_acl, ...rest } = data
30
+ return {
31
+ ...rest,
32
+ ...(enforce_acl !== undefined && { enforce_acl: enforce_acl ? enforce_acl.split(',') : [] }),
33
+ ...(sys_policy && { policy: sys_policy }),
34
+ }
35
+ })
36
+
37
+ const RestRouteSchema = BaseRouteSchema.omit({ $id: true }).extend({
38
+ operation_script: z.string().default(''),
39
+ http_method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']).default('GET'),
40
+ relative_path: z.string().default('/'),
41
+ requires_acl_authorization: z.boolean().default(true),
42
+ requires_authentication: z.boolean().default(true),
43
+ requires_snc_internal_role: z.boolean().default(true),
44
+ sys_policy: z.enum(['', 'read', 'protected']).default(''),
45
+ enforce_acl: z.string().default(''),
46
+ web_service_version: z.string().default(''),
47
+ })
48
+
49
+ export const RestRouteTransformer = RestRouteSchema.partial().transform((data) => {
50
+ const {
51
+ operation_script,
52
+ http_method,
53
+ relative_path,
54
+ requires_acl_authorization,
55
+ requires_authentication,
56
+ requires_snc_internal_role,
57
+ sys_policy,
58
+ enforce_acl,
59
+ ...rest
60
+ } = data
61
+ return {
62
+ ...rest,
63
+ ...(enforce_acl !== undefined && { enforce_acl: enforce_acl ? enforce_acl.split(',') : [] }),
64
+ ...(operation_script !== undefined && { script: operation_script }),
65
+ ...(http_method && { method: http_method }),
66
+ ...(relative_path && { path: relative_path }),
67
+ ...(requires_acl_authorization !== undefined && { authorization: requires_acl_authorization }),
68
+ ...(requires_authentication !== undefined && { authentication: requires_authentication }),
69
+ ...(requires_snc_internal_role !== undefined && { internalRole: requires_snc_internal_role }),
70
+ ...(sys_policy && { policy: sys_policy }),
71
+ }
72
+ })