@servicenow/sdk-build-plugins 2.0.1 → 2.1.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 (133) hide show
  1. package/dist/AttachmentPlugin.d.ts +8 -6
  2. package/dist/AttachmentPlugin.js +4 -2
  3. package/dist/AttachmentPlugin.js.map +1 -1
  4. package/dist/BusinessRulePlugin.d.ts +5 -31
  5. package/dist/BusinessRulePlugin.js +45 -72
  6. package/dist/BusinessRulePlugin.js.map +1 -1
  7. package/dist/CrossScopePrivilegePlugin.d.ts +14 -1
  8. package/dist/CrossScopePrivilegePlugin.js +36 -1
  9. package/dist/CrossScopePrivilegePlugin.js.map +1 -1
  10. package/dist/DefaultPlugin.d.ts +60 -57
  11. package/dist/DefaultPlugin.js +151 -146
  12. package/dist/DefaultPlugin.js.map +1 -1
  13. package/dist/HtmlTemplatePlugin.d.ts +21 -0
  14. package/dist/HtmlTemplatePlugin.js +52 -0
  15. package/dist/HtmlTemplatePlugin.js.map +1 -0
  16. package/dist/IdPlugin.d.ts +18 -8
  17. package/dist/IdPlugin.js +55 -28
  18. package/dist/IdPlugin.js.map +1 -1
  19. package/dist/JsonPlugin.d.ts +23 -0
  20. package/dist/JsonPlugin.js +74 -0
  21. package/dist/JsonPlugin.js.map +1 -0
  22. package/dist/ListPlugin.d.ts +7 -13
  23. package/dist/ListPlugin.js +32 -15
  24. package/dist/ListPlugin.js.map +1 -1
  25. package/dist/NowConfigPlugin.d.ts +45 -0
  26. package/dist/NowConfigPlugin.js +90 -0
  27. package/dist/NowConfigPlugin.js.map +1 -0
  28. package/dist/PackageJsonPlugin.d.ts +20 -0
  29. package/dist/PackageJsonPlugin.js +48 -0
  30. package/dist/PackageJsonPlugin.js.map +1 -0
  31. package/dist/PropertyPlugin.d.ts +9 -35
  32. package/dist/PropertyPlugin.js +53 -32
  33. package/dist/PropertyPlugin.js.map +1 -1
  34. package/dist/ScriptTemplatePlugin.d.ts +3 -20
  35. package/dist/ScriptTemplatePlugin.js +20 -138
  36. package/dist/ScriptTemplatePlugin.js.map +1 -1
  37. package/dist/ServerModulePlugin.d.ts +62 -0
  38. package/dist/ServerModulePlugin.js +231 -0
  39. package/dist/ServerModulePlugin.js.map +1 -0
  40. package/dist/UserPreferencePlugin.d.ts +4 -1
  41. package/dist/UserPreferencePlugin.js +12 -10
  42. package/dist/UserPreferencePlugin.js.map +1 -1
  43. package/dist/aclAndRole/AclPlugin.d.ts +41 -79
  44. package/dist/aclAndRole/AclPlugin.js +50 -72
  45. package/dist/aclAndRole/AclPlugin.js.map +1 -1
  46. package/dist/aclAndRole/RolePlugin.d.ts +27 -18
  47. package/dist/aclAndRole/RolePlugin.js +66 -41
  48. package/dist/aclAndRole/RolePlugin.js.map +1 -1
  49. package/dist/app/ApplicationMenuPlugin.d.ts +4 -2
  50. package/dist/app/ApplicationMenuPlugin.js +12 -7
  51. package/dist/app/ApplicationMenuPlugin.js.map +1 -1
  52. package/dist/atf/ATFComposer.js +324 -324
  53. package/dist/atf/TestPlugin.d.ts +12 -10
  54. package/dist/atf/TestPlugin.js +14 -12
  55. package/dist/atf/TestPlugin.js.map +1 -1
  56. package/dist/db/ColumnPlugins.d.ts +559 -97
  57. package/dist/db/ColumnPlugins.js +28 -24
  58. package/dist/db/ColumnPlugins.js.map +1 -1
  59. package/dist/db/DBUtils.d.ts +2 -0
  60. package/dist/db/DBUtils.js +27 -0
  61. package/dist/db/DBUtils.js.map +1 -0
  62. package/dist/db/DocumentationPlugin.d.ts +58 -0
  63. package/dist/db/DocumentationPlugin.js +248 -0
  64. package/dist/db/DocumentationPlugin.js.map +1 -0
  65. package/dist/db/RecordPlugin.d.ts +15 -13
  66. package/dist/db/RecordPlugin.js +74 -79
  67. package/dist/db/RecordPlugin.js.map +1 -1
  68. package/dist/db/TablePlugin.d.ts +38 -105
  69. package/dist/db/TablePlugin.js +205 -111
  70. package/dist/db/TablePlugin.js.map +1 -1
  71. package/dist/db/index.d.ts +2 -0
  72. package/dist/db/index.js +4 -1
  73. package/dist/db/index.js.map +1 -1
  74. package/dist/index.d.ts +7 -2
  75. package/dist/index.js +12 -2
  76. package/dist/index.js.map +1 -1
  77. package/dist/scriptedRESTAPI/RESTDeserializationUtils.js +8 -6
  78. package/dist/scriptedRESTAPI/RESTDeserializationUtils.js.map +1 -1
  79. package/dist/scriptedRESTAPI/RESTSerializationUtils.js +7 -6
  80. package/dist/scriptedRESTAPI/RESTSerializationUtils.js.map +1 -1
  81. package/dist/scriptedRESTAPI/RestApiPlugin.d.ts +74 -85
  82. package/dist/scriptedRESTAPI/RestApiPlugin.js +71 -54
  83. package/dist/scriptedRESTAPI/RestApiPlugin.js.map +1 -1
  84. package/dist/scriptedRESTAPI/RestUtils.d.ts +2 -0
  85. package/dist/scriptedRESTAPI/RestUtils.js +37 -9
  86. package/dist/scriptedRESTAPI/RestUtils.js.map +1 -1
  87. package/dist/scripts/ClientScriptPlugin.d.ts +18 -16
  88. package/dist/scripts/ClientScriptPlugin.js +48 -45
  89. package/dist/scripts/ClientScriptPlugin.js.map +1 -1
  90. package/dist/scripts/scriptUtils.d.ts +0 -14
  91. package/dist/scripts/scriptUtils.js +0 -74
  92. package/dist/scripts/scriptUtils.js.map +1 -1
  93. package/dist/uxf/ExperiencePlugin.d.ts +31 -3
  94. package/dist/uxf/ExperiencePlugin.js +10 -4
  95. package/dist/uxf/ExperiencePlugin.js.map +1 -1
  96. package/dist/uxf/RoutesPlugin.d.ts +10 -3
  97. package/dist/uxf/RoutesPlugin.js +20 -14
  98. package/dist/uxf/RoutesPlugin.js.map +1 -1
  99. package/package.json +6 -6
  100. package/src/AttachmentPlugin.ts +10 -2
  101. package/src/BusinessRulePlugin.ts +79 -104
  102. package/src/CrossScopePrivilegePlugin.ts +65 -5
  103. package/src/DefaultPlugin.ts +181 -173
  104. package/src/HtmlTemplatePlugin.ts +31 -0
  105. package/src/IdPlugin.ts +59 -28
  106. package/src/JsonPlugin.ts +81 -0
  107. package/src/ListPlugin.ts +38 -19
  108. package/src/NowConfigPlugin.ts +72 -0
  109. package/src/PackageJsonPlugin.ts +24 -0
  110. package/src/PropertyPlugin.ts +60 -38
  111. package/src/ScriptTemplatePlugin.ts +22 -179
  112. package/src/ServerModulePlugin.ts +267 -0
  113. package/src/UserPreferencePlugin.ts +28 -19
  114. package/src/aclAndRole/AclPlugin.ts +78 -109
  115. package/src/aclAndRole/RolePlugin.ts +85 -58
  116. package/src/app/ApplicationMenuPlugin.ts +15 -11
  117. package/src/atf/ATFComposer.ts +1 -1
  118. package/src/atf/TestPlugin.ts +14 -12
  119. package/src/db/ColumnPlugins.ts +36 -37
  120. package/src/db/DBUtils.ts +36 -0
  121. package/src/db/DocumentationPlugin.ts +282 -0
  122. package/src/db/RecordPlugin.ts +96 -98
  123. package/src/db/TablePlugin.ts +278 -152
  124. package/src/db/index.ts +2 -0
  125. package/src/index.ts +7 -2
  126. package/src/scriptedRESTAPI/RESTDeserializationUtils.ts +15 -7
  127. package/src/scriptedRESTAPI/RESTSerializationUtils.ts +7 -6
  128. package/src/scriptedRESTAPI/RestApiPlugin.ts +85 -75
  129. package/src/scriptedRESTAPI/RestUtils.ts +44 -11
  130. package/src/scripts/ClientScriptPlugin.ts +64 -68
  131. package/src/scripts/scriptUtils.ts +0 -76
  132. package/src/uxf/ExperiencePlugin.ts +14 -13
  133. package/src/uxf/RoutesPlugin.ts +22 -27
package/src/db/index.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export * from './ColumnPlugins'
2
2
  export { default as TablePlugin, generateColumnExpression } from './TablePlugin'
3
3
  export { RecordPlugin } from './RecordPlugin'
4
+ export { default as DocumentationPlugin } from './DocumentationPlugin'
5
+ export * from './DBUtils'
package/src/index.ts CHANGED
@@ -4,7 +4,7 @@ export * from './atf'
4
4
  export { default as DefaultPlugin } from './DefaultPlugin'
5
5
  export { default as ApplicationMenuPlugin } from './app/ApplicationMenuPlugin'
6
6
  export { default as PropertyPlugin } from './PropertyPlugin'
7
- export { default as RestApiPlugin } from './scriptedRESTAPI/RestApiPlugin'
7
+ export { default as RestApiPlugin, RestApiPluginTechDebt } from './scriptedRESTAPI/RestApiPlugin'
8
8
  export { default as UserPreferencePlugin } from './UserPreferencePlugin'
9
9
  export { default as CrossScopePrivilegePlugin } from './CrossScopePrivilegePlugin'
10
10
  export { default as ClientScriptPlugin } from './scripts/ClientScriptPlugin'
@@ -12,5 +12,10 @@ export { default as BusinessRulePlugin } from './BusinessRulePlugin'
12
12
  export { default as ListPluginPlugin } from './ListPlugin'
13
13
  export { default as RolePlugin } from './aclAndRole/RolePlugin'
14
14
  export { default as AclPlugin } from './aclAndRole/AclPlugin'
15
- export { default as ScriptTemplatePlugin, UNIQUE_SCRIPT_FILES } from './ScriptTemplatePlugin'
15
+ export { default as ScriptTemplatePlugin } from './ScriptTemplatePlugin'
16
16
  export { default as IdPlugin } from './IdPlugin'
17
+ export { default as JsonPlugin } from './JsonPlugin'
18
+ export { default as HtmlTemplatePlugin } from './HtmlTemplatePlugin'
19
+ export { default as NowConfigPlugin } from './NowConfigPlugin'
20
+ export { default as PackageJsonPlugin } from './PackageJsonPlugin'
21
+ export { default as ServerModulePlugin } from './ServerModulePlugin'
@@ -21,7 +21,13 @@ import {
21
21
  RouteAttrWithOutIdSchema,
22
22
  RestRouteTransformer,
23
23
  } from './RestSchemaUtils'
24
- import { getArgs, potentialRecordCallRouteParams, isParamAssociated, createRecordCall } from './RestUtils'
24
+ import {
25
+ getArgs,
26
+ potentialRecordCallRouteParams,
27
+ isParamAssociated,
28
+ createRecordCall,
29
+ removeNodeAndCleanUpExport,
30
+ } from './RestUtils'
25
31
  import { Record } from '@servicenow/sdk-core/runtime/db'
26
32
  import { isEqual } from 'lodash'
27
33
 
@@ -154,14 +160,14 @@ export function transformRouteAttrs(document: Document, context: Context, argNam
154
160
  '[]'
155
161
  )
156
162
  const routeAttrIterator = new ArrayIterator(routeAttrsNode)
157
- const arrayExpression = routeArrayIterator.getExpression()
163
+ const arrayExpression = routeAttrIterator.getExpression()
158
164
  while (routeAttrIterator.hasNext()) {
159
165
  const attrElement = routeAttrIterator.next()
160
166
  const attrId = getNodeId(attrElement.asKindOrThrow(SyntaxKind.ObjectLiteralExpression))
161
167
  const attrSysId = context.keys.explicit[attrId!]?.id
162
168
  if (attrSysId === document.guid) {
163
169
  if (document.action === 'DELETE') {
164
- arrayExpression.removeElement(element)
170
+ arrayExpression.removeElement(attrElement)
165
171
  } else {
166
172
  const attrEleObj = attrElement.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
167
173
  cleanUpDefault(RouteAttrWithOutIdSchema, routeAttrData, attrEleObj)
@@ -238,7 +244,7 @@ export function transformRoutes(document: Document, context: Context, documentMa
238
244
  const eleObj = element.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
239
245
  transformEnforceAcl(eleObj, enforce_acl, context)
240
246
  if (script !== undefined) {
241
- processScript(eleObj, 'script', script, document.guid, 'sys_ws_operation', context)
247
+ processScript(eleObj, 'script', script)
242
248
  }
243
249
  cleanUpDefault(RouteSchema, parsedRouteData, eleObj)
244
250
  mergeDataIntoObjectLiteral(eleObj, parsedRouteData)
@@ -254,7 +260,7 @@ export function transformRoutes(document: Document, context: Context, documentMa
254
260
  .asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
255
261
  transformEnforceAcl(element, enforce_acl, context)
256
262
  if (script !== undefined) {
257
- processScript(element, 'script', script, document.guid, 'sys_ws_operation', context)
263
+ processScript(element, 'script', script)
258
264
  }
259
265
  transformId(element, '$id', document.guid, 'sys_ws_operation', context)
260
266
  return true
@@ -307,7 +313,7 @@ export function transformRouteAttrsMap<T>(
307
313
  getCallExpressionName(attrDoc.node as ts.CallExpression) === Record.name
308
314
  ) {
309
315
  const attrId = getNodeId(getArgs(attrDoc))!
310
- removeNode(attrDoc.node)
316
+ removeNodeAndCleanUpExport(attrDoc.node)
311
317
  delete context.keys.explicit[attrId]
312
318
  }
313
319
  const attrInfo = attrDoc.data!['data']
@@ -364,8 +370,9 @@ export function transformRouteAttrsMap<T>(
364
370
  if (!isHandled && document.action !== 'DELETE' && routeSysId === operationId) {
365
371
  cleanUpDefault(RouteAttrWithOutIdSchema, parsedAttrData)
366
372
  const element = attrExpression
367
- .addElement(stringify(parsedAttrData))
373
+ .addElement(stringify({}))
368
374
  .asKindOrThrow(SyntaxKind.ObjectLiteralExpression)
375
+ mergeDataIntoObjectLiteral(element, parsedAttrData)
369
376
  const table = argName === 'headers' ? 'sys_ws_header' : 'sys_ws_query_parameter'
370
377
  const foundAttrId = context.keys.findExplicitKeyById(attrId)
371
378
 
@@ -404,6 +411,7 @@ export function transformRouteAttrsMap<T>(
404
411
  potentialRecordCallRouteParams.has(deletedParamID)
405
412
  ) {
406
413
  createRecordCall(deletedParamID, context)
414
+ potentialRecordCallRouteParams.delete(deletedParamID)
407
415
  }
408
416
  }
409
417
  return true
@@ -33,7 +33,7 @@ export function generateVersionRecords(
33
33
  short_description: version.short_description,
34
34
  version: version.version,
35
35
  version_id: versionId,
36
- web_service_definition: apiRecord,
36
+ web_service_definition: apiRecord.$id as any,
37
37
  },
38
38
  })
39
39
  versionsRecords.push(versionRecord)
@@ -76,7 +76,7 @@ export function generateRouteAttributesRecords<T extends TableName, M extends Ta
76
76
  required: attribute.required,
77
77
  short_description: attribute.short_description,
78
78
  example_value: attribute.example_value,
79
- web_service_definition: apiRecord,
79
+ web_service_definition: apiRecord.$id,
80
80
  } as Data<T>,
81
81
  })
82
82
  /**
@@ -97,8 +97,8 @@ export function generateRouteAttributesRecords<T extends TableName, M extends Ta
97
97
  table: mapping_collection,
98
98
  $id: attrMapId,
99
99
  data: {
100
- web_service_operation: routeRecord,
101
- [attrField]: attributeRecord,
100
+ web_service_operation: routeRecord.$id,
101
+ [attrField]: attributeRecord.$id,
102
102
  } as unknown as Data<M>,
103
103
  })
104
104
  attributeRecords.push(attrMapRecord)
@@ -150,6 +150,7 @@ export function generateRoutesAndRouteAttrRecords(
150
150
  ? `${baseOperationURI}/v${route.version}/${remOperationURI}`
151
151
  : `${baseOperationURI}/${remOperationURI}`
152
152
 
153
+ const version = getRestRouteVersion(route, versionMap)
153
154
  const routeRecord = Record({
154
155
  table: 'sys_ws_operation',
155
156
  $id: context.keys.registerExplicitId('sys_ws_operation', route.$id),
@@ -171,8 +172,8 @@ export function generateRoutesAndRouteAttrRecords(
171
172
  requires_snc_internal_role: route.internalRole,
172
173
  short_description: route.short_description,
173
174
  request_example: route.request_example,
174
- web_service_definition: apiRecord,
175
- web_service_version: getRestRouteVersion(route, versionMap),
175
+ web_service_definition: apiRecord.$id as any,
176
+ web_service_version: typeof version === 'object' ? (version.$id as any) : version,
176
177
  ...(route.policy && { sys_policy: route.policy }),
177
178
  },
178
179
  })
@@ -12,9 +12,10 @@ import {
12
12
  getSysUpdateName,
13
13
  EntityData,
14
14
  ObjectData,
15
+ Data,
16
+ FluentDiagnostic,
15
17
  } from '@servicenow/sdk-build-core'
16
18
  import { RecordPlugin } from '../db/RecordPlugin'
17
- import { buildScriptImport, scriptInfo, type ScriptInfo } from '../scripts/scriptUtils'
18
19
  import {
19
20
  EnforceAcl,
20
21
  mergeACLIds,
@@ -47,6 +48,7 @@ import {
47
48
  } from './RestUtils'
48
49
  import * as z from 'zod'
49
50
  import { Diagnostic } from '@servicenow/sdk-project'
51
+ import { ModuleFunctionData } from '../ServerModulePlugin'
50
52
 
51
53
  const methodsAllowedToOverrideRequests = ['PUT', 'PATCH', 'POST']
52
54
  const parseAcls = (enforce_acl: EnforceAcl, context: Context) =>
@@ -77,6 +79,30 @@ function restApiAsRecord<I extends number, V extends Version<I>>(config: RestApi
77
79
  })
78
80
  }
79
81
 
82
+ /**
83
+ * TODO: Apparently the REST API plugin's arranger actually has pretty severe side effects such as
84
+ * transforming code and dropping keys from the registry. I failed to unravel the web of code spread
85
+ * across all the REST API "utils" files to understand how and why it is doing this. For some reason
86
+ * this is only an issue when doing a regular build and not during bidirectional sync... For now I'm
87
+ * preserving the existing behavior of skipping the arranger during regular builds and putting that
88
+ * logic here in this namespace so we can easily find it and rip it out later.
89
+ *
90
+ * @deprecated
91
+ */
92
+ export namespace RestApiPluginTechDebt {
93
+ export function applyArrangerSkipFlag(context: Context) {
94
+ context['skipRestApiArranger'] = true
95
+ }
96
+
97
+ export function removeArrangerSkipFlag(context: Context) {
98
+ delete context['skipRestApiArranger']
99
+ }
100
+
101
+ export function shouldSkipArranger(context: Context) {
102
+ return context['skipRestApiArranger'] === true
103
+ }
104
+ }
105
+
80
106
  export default Plugin({
81
107
  name: 'RestApi',
82
108
  ownedTables: {
@@ -86,85 +112,70 @@ export default Plugin({
86
112
  },
87
113
  extractors: {
88
114
  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
115
+ fluent: {
116
+ CallExpression: (node, context) => {
117
+ const result = extractCallExpression(RestApi, 'restApi', node, context, (restApi) =>
118
+ context.registerExplicitId('sys_ws_definition', restApi.$id as string)
119
+ )
105
120
 
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
- )
121
+ if (!result.handled || !(0 in result.data)) {
122
+ return result
115
123
  }
116
124
 
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
+ const restApiEntity = result.data[0]
126
+ const entityData = RestApiSchema.parse(restApiEntity.getValue())
127
+ const { routes, enforce_acl, consumes, produces } = entityData
128
+ const routesData = restApiEntity.getProperty('routes', 'array')?.getElements() ?? []
129
+ for (let i = 0; i < routesData.length; i++) {
130
+ const routeData = routesData[i]!
131
+ if (!Data.isObject(routeData)) {
132
+ result.diagnostics.push(new FluentDiagnostic(routeData.getNode(), 'Invalid route value'))
133
+ continue
134
+ }
125
135
 
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
- }
136
+ const scriptData = routeData.getProperty('script')
137
+ const scriptValue =
138
+ scriptData instanceof ModuleFunctionData
139
+ ? scriptData.getGlueCode((n) => `${n}(request, response)`)
140
+ : scriptData.getValue()?.toString() ?? ''
130
141
 
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
- }
142
+ const route = routes[i]!
143
+ route.script = scriptValue
157
144
 
158
- return { handled: true, diagnostics: [], data: [info] }
159
- },
145
+ /** allow users to override consumes for allowed http methods*/
146
+ if (
147
+ route.consumes &&
148
+ route.consumes !== consumes &&
149
+ !methodsAllowedToOverrideRequests.includes(route.method)
150
+ ) {
151
+ throw Error(`Cannot override consumer type for ${route.method} method`)
152
+ }
160
153
 
161
- FunctionExpression(node, context) {
162
- const info = scriptInfo(node, context, RestApi.name)
163
- if (!info) {
164
- return { handled: false }
165
- }
154
+ route.name = route.name ? route.name : route.path
155
+ route.consumes = route.consumes ? route.consumes : consumes
156
+ route.produces = route.produces ? route.produces : produces
157
+ route.enforce_acl = parseAcls(route.enforce_acl, context)
158
+ }
166
159
 
167
- return { handled: true, diagnostics: [], data: [info] }
160
+ return {
161
+ handled: true,
162
+ diagnostics: result.diagnostics,
163
+ data: [
164
+ new EntityData(
165
+ restApiEntity.getKind(),
166
+ restApiEntity.getGuid(),
167
+ ObjectData.fromObjectValue(
168
+ {
169
+ ...entityData,
170
+ enforce_acl: parseAcls(enforce_acl, context),
171
+ },
172
+ restApiEntity.getNode()
173
+ ),
174
+ restApiEntity.getNode()
175
+ ),
176
+ ],
177
+ }
178
+ },
168
179
  },
169
180
  },
170
181
  },
@@ -241,8 +252,7 @@ export default Plugin({
241
252
  arrangers: {
242
253
  record(document, context) {
243
254
  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') {
255
+ if (!restTables.includes(table) || RestApiPluginTechDebt.shouldSkipArranger(context)) {
246
256
  return { handled: false }
247
257
  }
248
258
 
@@ -352,7 +362,7 @@ export default Plugin({
352
362
  doc.guid === (document.data as any).data.web_service_definition
353
363
  )
354
364
  // eslint-disable-next-line no-case-declarations
355
- const o_v_node = document.parent!.node ? document.parent!.node : restDef?.node
365
+ const o_v_node = document.parent?.node ? document.parent!.node : restDef?.node
356
366
  if (!o_v_node) {
357
367
  return undefined
358
368
  }
@@ -14,6 +14,7 @@ import {
14
14
  import { isEqual } from 'lodash'
15
15
  import { RestApi } from '@servicenow/sdk-core/runtime/rest'
16
16
  import { RecordPlugin } from '../db/RecordPlugin'
17
+ import { SupportedNode } from '@servicenow/sdk-project'
17
18
 
18
19
  export const restTables = [
19
20
  'sys_ws_definition',
@@ -48,7 +49,7 @@ export function getRouteAttrMapResult(document: Document, restDocMap: any): Resu
48
49
  * if the given attribute map record references query parameter or routes record
49
50
  * not part of the current app we make it a record call.
50
51
  */
51
- const isUnHandled = restDocMap['unHandled_records'].find((doc) => doc.id === document.guid)
52
+ const isUnHandled = restDocMap['unHandled_records'].find((doc) => doc.guid === document.guid)
52
53
  if (isUnHandled) {
53
54
  return { handled: false }
54
55
  }
@@ -150,6 +151,20 @@ export function getRouteAttrWithRestNodeResult(
150
151
  return { handled: true, result: { kind: 'record', guid: nodeRestId } }
151
152
  }
152
153
  if (restId === nodeRestId) {
154
+ /**
155
+ * Handles the case where the attribute associated with the rest node is not consumed by any m2m record.
156
+ * Probabal cause is it's being removed from the rest node and needs a separate record call.
157
+ */
158
+ if (!isConsumedByRest(restId, restDocMap, document)) {
159
+ deleteDocNode(document, context)
160
+ document['changedData'] = { data: document.data!['data'] }
161
+ const expKey = context.keys.findExplicitKeyById(document.guid)
162
+ if (expKey) {
163
+ delete context.keys.explicit[expKey]
164
+ }
165
+ potentialRecordCallRouteParams.delete(document.guid)
166
+ return { handled: false }
167
+ }
153
168
  return { handled: true, result: { kind: 'record', guid: restId } }
154
169
  }
155
170
  const attrName = document.data!['table'] === 'sys_ws_header' ? 'headers' : 'parameters'
@@ -179,7 +194,7 @@ export function getRouteAttrWithRestNodeResult(
179
194
 
180
195
  function isConsumed(document: Document, restDocMap: any) {
181
196
  const restId = document.data!['data']['web_service_definition']
182
- const isUnHandled = restDocMap['unHandled_records'].find((doc) => doc.id === document.guid)
197
+ const isUnHandled = restDocMap['unHandled_records'].find((doc) => doc.guid === document.guid)
183
198
  if (isUnHandled) {
184
199
  return false
185
200
  }
@@ -213,7 +228,7 @@ export function getRouteAttrWithRecordNodeResult(
213
228
  return { handled: false }
214
229
  }
215
230
  const recordId = getNodeId(getArgs(document))!
216
- removeNode(document.node!)
231
+ removeNodeAndCleanUpExport(document.node!)
217
232
  deleteDocNode(document, context)
218
233
  delete context.keys.explicit[recordId]
219
234
  document['changedData'] = { data: document.data!['data'] }
@@ -227,7 +242,9 @@ const getRestIdForRoute = (routeId: string, restDocMap: any) => {
227
242
  .filter((key) => key !== 'unHanlded_records' && key !== 'delete_records')
228
243
  .forEach((key) => {
229
244
  if (restDocMap[key].routes) {
230
- const foundRoute = Object.values(restDocMap[key].routes).find((doc: any) => doc.id === routeId)
245
+ const foundRoute = Object.values(restDocMap[key].routes).find(
246
+ (doc) => (doc as Document).guid === routeId
247
+ )
231
248
  if (foundRoute) {
232
249
  restId = key
233
250
  }
@@ -277,7 +294,7 @@ export function getRouteAttrMapWithRestNodeResult(
277
294
  if (document.action === 'DELETE') {
278
295
  return { handled: true, result: { kind: 'record', guid: routeId } }
279
296
  }
280
- const isUnHandled = restDocMap['unHandled_records'].find((doc) => doc.id === document.guid)
297
+ const isUnHandled = restDocMap['unHandled_records'].find((doc: Document) => doc.guid === document.guid)
281
298
  const attrName = document.data!['table'] === 'sys_ws_header_map' ? 'headers' : 'parameters'
282
299
  if (isUnHandled) {
283
300
  let unAssociatedId: string | undefined = undefined
@@ -328,7 +345,7 @@ export function getRouteAttrMapWithRecordNodeResult(
328
345
  return { handled: false }
329
346
  }
330
347
  const routeId = document.data!['data']['web_service_operation']
331
- const isUnHandled = restDocMap['unHandled_records'].find((doc) => doc.id === document.guid)
348
+ const isUnHandled = restDocMap['unHandled_records'].find((doc: Document) => doc.guid === document.guid)
332
349
  if (isUnHandled) {
333
350
  return { handled: false }
334
351
  }
@@ -337,7 +354,7 @@ export function getRouteAttrMapWithRecordNodeResult(
337
354
  const paramField =
338
355
  document.data!['table'] === 'sys_ws_header_map' ? 'web_service_header' : 'web_service_query_parameter'
339
356
  potentialRecordCallRouteParams.delete(document.data!['data'][paramField])
340
- removeNode(document.node!)
357
+ removeNodeAndCleanUpExport(document.node!)
341
358
  deleteDocNode(document, context)
342
359
  delete context.keys.explicit[recordId]
343
360
  return { handled: true, result: { kind: 'record', guid: routeId } }
@@ -357,8 +374,8 @@ export function getRouteAttrResult(document: Document, restDocMap: any): Result<
357
374
  return { handled: false }
358
375
  }
359
376
 
360
- const findRecInDocs = (docs: any[], id: string, table: string) => {
361
- return docs?.find((doc) => doc.data!['table'] === table && doc.id == id)
377
+ const findRecInDocs = (docs: Document[], id: string, table: string) => {
378
+ return docs?.find((doc) => doc.data!['table'] === table && doc.guid == id)
362
379
  }
363
380
 
364
381
  export function getRestDocumentMap(context: Context) {
@@ -372,7 +389,7 @@ export function getRestDocumentMap(context: Context) {
372
389
  const doc2Table = doc2.data!['table']
373
390
  return restTables.indexOf(doc1Table) - restTables.indexOf(doc2Table)
374
391
  })
375
- const unHandledDocs: any[] = []
392
+ const unHandledDocs: Document[] = []
376
393
  /** filters and gets all delete records and insert_or_update records */
377
394
  const delRestDocs = allRestDocs.filter((doc) => doc.action === 'DELETE')
378
395
  const existingDocs = allRestDocs.filter((doc) => doc.action !== 'DELETE')
@@ -503,5 +520,21 @@ export function createRecordCall(paramSysId: string, context: Context) {
503
520
  document['changedData'] = { data: document.data!['data'] }
504
521
  delete document?.node
505
522
  const linkedDoc = RecordPlugin.generators.record(document as UnlinkedDocument<'record'> & Arranged, context)
506
- RecordPlugin.transformers.record.CallExpression(linkedDoc)
523
+ RecordPlugin.transformers.record.CallExpression(linkedDoc, context)
524
+ }
525
+
526
+ export function removeNodeAndCleanUpExport(node: SupportedNode) {
527
+ const sourceFile = node.getSourceFile()
528
+ removeNode(node)
529
+ sourceFile
530
+ .getDefaultExportSymbol()
531
+ ?.getDeclarations()
532
+ .forEach((declaration) => {
533
+ if (
534
+ declaration?.isKind(ts.SyntaxKind.ExportAssignment) &&
535
+ declaration.getExpression()?.getText() === 'undefined'
536
+ ) {
537
+ declaration.remove()
538
+ }
539
+ })
507
540
  }