@servicenow/sdk-build-plugins 4.0.1 → 4.1.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 (111) hide show
  1. package/dist/acl-plugin.js +23 -16
  2. package/dist/acl-plugin.js.map +1 -1
  3. package/dist/application-menu-plugin.js +15 -14
  4. package/dist/application-menu-plugin.js.map +1 -1
  5. package/dist/atf/test-plugin.js +37 -34
  6. package/dist/atf/test-plugin.js.map +1 -1
  7. package/dist/basic-syntax-plugin.js +50 -1
  8. package/dist/basic-syntax-plugin.js.map +1 -1
  9. package/dist/business-rule-plugin.js +12 -10
  10. package/dist/business-rule-plugin.js.map +1 -1
  11. package/dist/claims-plugin.d.ts +3 -0
  12. package/dist/claims-plugin.js +95 -0
  13. package/dist/claims-plugin.js.map +1 -0
  14. package/dist/client-script-plugin.js +1 -1
  15. package/dist/client-script-plugin.js.map +1 -1
  16. package/dist/column/column-to-record.d.ts +3 -3
  17. package/dist/column/column-to-record.js +17 -16
  18. package/dist/column/column-to-record.js.map +1 -1
  19. package/dist/column-plugin.js +86 -8
  20. package/dist/column-plugin.js.map +1 -1
  21. package/dist/cross-scope-privilege-plugin.js +17 -3
  22. package/dist/cross-scope-privilege-plugin.js.map +1 -1
  23. package/dist/html-import-plugin.js +8 -1
  24. package/dist/html-import-plugin.js.map +1 -1
  25. package/dist/index.d.ts +2 -1
  26. package/dist/index.js +3 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/json-plugin.d.ts +7 -2
  29. package/dist/json-plugin.js +28 -12
  30. package/dist/json-plugin.js.map +1 -1
  31. package/dist/list-plugin.js +29 -17
  32. package/dist/list-plugin.js.map +1 -1
  33. package/dist/now-config-plugin.js +14 -5
  34. package/dist/now-config-plugin.js.map +1 -1
  35. package/dist/now-include-plugin.d.ts +6 -7
  36. package/dist/now-include-plugin.js +59 -26
  37. package/dist/now-include-plugin.js.map +1 -1
  38. package/dist/now-ref-plugin.js +1 -1
  39. package/dist/now-ref-plugin.js.map +1 -1
  40. package/dist/package-json-plugin.js +5 -7
  41. package/dist/package-json-plugin.js.map +1 -1
  42. package/dist/property-plugin.js +1 -1
  43. package/dist/property-plugin.js.map +1 -1
  44. package/dist/record-plugin.js +23 -9
  45. package/dist/record-plugin.js.map +1 -1
  46. package/dist/repack/index.d.ts +2 -0
  47. package/dist/repack/index.js +8 -0
  48. package/dist/repack/index.js.map +1 -1
  49. package/dist/rest-api-plugin.js +12 -12
  50. package/dist/rest-api-plugin.js.map +1 -1
  51. package/dist/role-plugin.js +18 -16
  52. package/dist/role-plugin.js.map +1 -1
  53. package/dist/script-action-plugin.js +1 -1
  54. package/dist/script-action-plugin.js.map +1 -1
  55. package/dist/script-include-plugin.js +6 -4
  56. package/dist/script-include-plugin.js.map +1 -1
  57. package/dist/server-module-plugin/index.d.ts +3 -1
  58. package/dist/server-module-plugin/index.js +110 -28
  59. package/dist/server-module-plugin/index.js.map +1 -1
  60. package/dist/service-portal/angular-provider-plugin.js +3 -3
  61. package/dist/service-portal/angular-provider-plugin.js.map +1 -1
  62. package/dist/service-portal/dependency-plugin.js +9 -12
  63. package/dist/service-portal/dependency-plugin.js.map +1 -1
  64. package/dist/service-portal/widget-plugin.js +8 -8
  65. package/dist/service-portal/widget-plugin.js.map +1 -1
  66. package/dist/static-content-plugin.d.ts +2 -0
  67. package/dist/static-content-plugin.js +16 -13
  68. package/dist/static-content-plugin.js.map +1 -1
  69. package/dist/table-plugin.js +55 -33
  70. package/dist/table-plugin.js.map +1 -1
  71. package/dist/ui-action-plugin.js +29 -19
  72. package/dist/ui-action-plugin.js.map +1 -1
  73. package/dist/ui-page-plugin.js +6 -3
  74. package/dist/ui-page-plugin.js.map +1 -1
  75. package/dist/user-preference-plugin.js +2 -2
  76. package/dist/user-preference-plugin.js.map +1 -1
  77. package/package.json +5 -5
  78. package/src/acl-plugin.ts +31 -27
  79. package/src/application-menu-plugin.ts +39 -39
  80. package/src/atf/test-plugin.ts +82 -81
  81. package/src/basic-syntax-plugin.ts +54 -1
  82. package/src/business-rule-plugin.ts +74 -73
  83. package/src/claims-plugin.ts +116 -0
  84. package/src/client-script-plugin.ts +1 -1
  85. package/src/column/column-to-record.ts +59 -53
  86. package/src/column-plugin.ts +93 -8
  87. package/src/cross-scope-privilege-plugin.ts +18 -3
  88. package/src/html-import-plugin.ts +12 -2
  89. package/src/index.ts +2 -1
  90. package/src/json-plugin.ts +35 -15
  91. package/src/list-plugin.ts +39 -30
  92. package/src/now-config-plugin.ts +19 -8
  93. package/src/now-include-plugin.ts +64 -30
  94. package/src/now-ref-plugin.ts +1 -1
  95. package/src/package-json-plugin.ts +7 -6
  96. package/src/property-plugin.ts +1 -1
  97. package/src/record-plugin.ts +25 -9
  98. package/src/repack/index.ts +14 -0
  99. package/src/rest-api-plugin.ts +15 -15
  100. package/src/role-plugin.ts +15 -15
  101. package/src/script-action-plugin.ts +1 -1
  102. package/src/script-include-plugin.ts +7 -4
  103. package/src/server-module-plugin/index.ts +158 -43
  104. package/src/service-portal/angular-provider-plugin.ts +12 -10
  105. package/src/service-portal/dependency-plugin.ts +12 -13
  106. package/src/service-portal/widget-plugin.ts +36 -30
  107. package/src/static-content-plugin.ts +12 -10
  108. package/src/table-plugin.ts +71 -56
  109. package/src/ui-action-plugin.ts +49 -33
  110. package/src/ui-page-plugin.ts +6 -3
  111. package/src/user-preference-plugin.ts +2 -2
@@ -1,4 +1,4 @@
1
- import { isSNScope } from '@servicenow/sdk-build-core'
1
+ import { isSNScope, type Record } from '@servicenow/sdk-build-core'
2
2
  import { CallExpressionShape, Plugin } from '@servicenow/sdk-build-core'
3
3
  import { generateDeprecatedDiagnostics } from './utils'
4
4
 
@@ -77,7 +77,7 @@ export const RolePlugin = Plugin.create({
77
77
  diagnostics.error(name.getOriginalNode(), `Role name must begin with '${scope}.'`)
78
78
  }
79
79
 
80
- const role = factory.createRecord({
80
+ const role = await factory.createRecord({
81
81
  explicitId: arg.get('$id'),
82
82
  source: callExpression,
83
83
  table: 'sys_user_role',
@@ -98,26 +98,26 @@ export const RolePlugin = Plugin.create({
98
98
  })),
99
99
  })
100
100
 
101
- const containedRoles = arg
102
- .get('containsRoles')
103
- .ifArray()
104
- ?.map((e) =>
105
- factory.createRecord({
101
+ const containedRoles: Record[] = []
102
+ for (const e of arg.get('containsRoles').ifArray()?.getElements() ?? []) {
103
+ containedRoles.push(
104
+ await factory.createRecord({
106
105
  source: callExpression,
107
106
  table: 'sys_user_role_contains',
108
107
  properties: {
109
108
  role,
110
- contains:
111
- e.ifStringLiteral()?.pipe((roleName) =>
112
- factory.createReference({
113
- source: roleName,
114
- table: 'sys_user_role',
115
- keys: { name: roleName },
116
- })
117
- ) ?? e,
109
+ contains: e.isStringLiteral()
110
+ ? await factory.createReference({
111
+ source: e,
112
+ table: 'sys_user_role',
113
+ keys: { name: e },
114
+ })
115
+ : e,
118
116
  },
119
117
  })
120
118
  )
119
+ }
120
+
121
121
  return {
122
122
  success: true,
123
123
  value: role.with(...(containedRoles ?? [])),
@@ -39,7 +39,7 @@ export const ScriptActionPlugin = Plugin.create({
39
39
  }
40
40
 
41
41
  const args = callExpression.getArgument(0).asObject()
42
- const record = factory.createRecord({
42
+ const record = await factory.createRecord({
43
43
  source: callExpression,
44
44
  table: 'sysevent_script_action',
45
45
  explicitId: args.get('$id'),
@@ -1,5 +1,6 @@
1
1
  import { CallExpressionShape, isSNScope, Plugin } from '@servicenow/sdk-build-core'
2
2
  import { NowIdShape } from './now-id-plugin'
3
+ import { NowIncludeShape } from './now-include-plugin'
3
4
 
4
5
  const nameRegex = /^[a-zA-Z_$][0-9a-zA-Z_$]+$/
5
6
 
@@ -7,7 +8,9 @@ export const ScriptIncludePlugin = Plugin.create({
7
8
  name: `ScriptIncludePlugin`,
8
9
  records: {
9
10
  sys_script_include: {
10
- toShape(record) {
11
+ async toShape(record, { transform }) {
12
+ const script = await NowIncludeShape.fromRecord(record, record.get('script'), transform)
13
+
11
14
  return {
12
15
  success: true,
13
16
  value: new CallExpressionShape({
@@ -17,9 +20,9 @@ export const ScriptIncludePlugin = Plugin.create({
17
20
  record.transform(({ $ }) => ({
18
21
  $id: $.val(NowIdShape.from(record)),
19
22
  name: $,
20
- script: $,
23
+ script: $.val(script),
21
24
  description: $.def(''),
22
- apiName: $.from('api_name').def(``),
25
+ apiName: $.from('api_name').def(''),
23
26
  callerAccess: $.from('caller_access').map((v) =>
24
27
  v
25
28
  .ifString()
@@ -67,7 +70,7 @@ export const ScriptIncludePlugin = Plugin.create({
67
70
 
68
71
  return {
69
72
  success: true,
70
- value: factory.createRecord({
73
+ value: await factory.createRecord({
71
74
  source: shape,
72
75
  table: 'sys_script_include',
73
76
  explicitId: prop.get('$id'),
@@ -10,13 +10,16 @@ import {
10
10
  type Project,
11
11
  type RecordContext,
12
12
  type Compiler,
13
+ type Package,
14
+ type Record,
13
15
  } from '@servicenow/sdk-build-core'
14
- import { path as pathModule, ts, type FileSystem, type NowConfig } from '@servicenow/sdk-build-core'
16
+ import { NowConfig, path as pathModule, ts, type FileSystem } from '@servicenow/sdk-build-core'
15
17
  import { RepackService } from '../repack'
16
18
  import { SBOMBuilder } from './sbom-builder'
17
19
  import isEqual from 'lodash/isEqual'
18
20
  import { INVALID_XML_CHARACTERS, applyPathMappings } from '../utils'
19
21
  import zip from 'lodash/zip'
22
+ import type { DependencyNode } from '@servicenow/sdk-repack'
20
23
 
21
24
  const GLUE_CODE_PREFIX = '// @fluent-module'
22
25
  const GLUE_CODE_META_REGEX = new RegExp(`^${GLUE_CODE_PREFIX} (.*);(true|false);(.*)`) // name;isDefault;path
@@ -29,22 +32,26 @@ const GLUE_CODE_WARNING = `
29
32
  // SDK from regenerating it. However, you will then be responsible for the
30
33
  // management of this code in your Fluent file.`
31
34
 
35
+ const NODE_MODULES = 'node_modules'
36
+
32
37
  type GlueCodeMeta = {
33
38
  name: string
34
39
  path: string
35
40
  isDefault: boolean
41
+ relativePath?: string
36
42
  }
37
43
 
38
- function isGlueCode(string: StringShape): boolean {
44
+ function isGlueCode(string: StringShape | string): boolean {
39
45
  return string.startsWith(GLUE_CODE_PREFIX)
40
46
  }
41
47
 
42
- function parseMeta(string: StringShape): GlueCodeMeta {
43
- const result = string.getValue().match(GLUE_CODE_META_REGEX)
48
+ function parseMeta(string: StringShape | string): GlueCodeMeta {
49
+ const value = typeof string === 'string' ? string : string.getValue()
50
+ const result = value.match(GLUE_CODE_META_REGEX)
44
51
  const [, name, isDefault, path] = result ?? []
45
52
 
46
53
  if (typeof name !== 'string' || typeof isDefault !== 'string' || typeof path !== 'string') {
47
- throw new Error(`Invalid glue code format: ${string.getValue()}`)
54
+ throw new Error(`Invalid glue code format: ${value}`)
48
55
  }
49
56
 
50
57
  return { name, path, isDefault: isDefault === 'true' }
@@ -62,34 +69,40 @@ export class ModuleFunctionShape extends Shape {
62
69
  callExpressionProvider: (functionName: string) => string = (name) => `${name}()`,
63
70
  defaultParams?: string[]
64
71
  ): StringShape {
65
- const { name, path, isDefault } = this.meta
72
+ const { name, path, isDefault, relativePath } = this.meta
66
73
  const moduleParamNames = getFunctionParameters(this.getSource())
74
+
67
75
  const variables = zip(defaultParams ?? [], moduleParamNames).map(
68
76
  ([defaultParam, moduleParamName]) => defaultParam ?? moduleParamName
69
77
  )
70
78
  const moduleCallExpression = callExpressionProvider(name).replace('{{PARAMS}}', variables.join(', '))
71
79
 
80
+ const requirePath = relativePath ?? path
81
+
72
82
  const code = isDefault
73
- ? `const ${name} = require('${path}').default;\n${moduleCallExpression};`
74
- : `const { ${name} } = require('${path}');\n${moduleCallExpression};`
83
+ ? `const ${name} = require('${requirePath}').default;\n${moduleCallExpression};`
84
+ : `const { ${name} } = require('${requirePath}');\n${moduleCallExpression};`
75
85
 
76
86
  return Shape.from(this, `${GLUE_CODE_PREFIX} ${name};${isDefault};${path}${GLUE_CODE_WARNING}\n${code}`)
77
87
  .asString()
78
88
  .withContentType('cdata')
79
89
  }
80
90
 
81
- override equals(other: Shape): boolean {
82
- if (other.is(ModuleFunctionShape)) {
91
+ override equals(other: unknown): boolean {
92
+ if (other instanceof ModuleFunctionShape) {
83
93
  return isEqual(this.meta, other.meta)
84
- } else if (other.isString()) {
85
- if (!isGlueCode(other)) {
94
+ }
95
+
96
+ const string = other instanceof StringShape ? other.getValue() : other
97
+ if (typeof string === 'string') {
98
+ if (!isGlueCode(string)) {
86
99
  return false
87
100
  }
88
101
 
89
- return isEqual(this.meta, parseMeta(other))
90
- } else {
91
- return super.equals(other)
102
+ return isEqual(this.meta, parseMeta(string))
92
103
  }
104
+
105
+ return super.equals(other)
93
106
  }
94
107
  }
95
108
 
@@ -147,7 +160,7 @@ function getFunctionParameters(source: Source): string[] {
147
160
 
148
161
  async function parseDeclaration(
149
162
  node: ts.FunctionDeclaration | ts.VariableDeclaration,
150
- { transform }: { transform: Transform }
163
+ { transform, project, config }: { transform: Transform; config: NowConfig; project: Project }
151
164
  ): Promise<Result<ModuleFunctionShape>> {
152
165
  const result = await transform.toRecord(node.getSourceFile())
153
166
  if (!result.success) {
@@ -159,11 +172,27 @@ async function parseDeclaration(
159
172
  return { success: false }
160
173
  }
161
174
 
175
+ const path = record.get('path').asString().getValue()
176
+
177
+ if (NowConfig.legacyPackageResolution(config) || config.scope === 'global') {
178
+ return {
179
+ success: true,
180
+ value: new ModuleFunctionShape(node, {
181
+ name: node.getName() ?? 'functionModule',
182
+ path: path,
183
+ isDefault: node.isDefaultExport(),
184
+ }),
185
+ }
186
+ }
187
+
188
+ const originalPath = (record.getSource() as SourceFileShape).getPath()
189
+ const relativePath = pathModule.relative(project.getRootDir(), project.resolvePath(originalPath))
162
190
  return {
163
191
  success: true,
164
192
  value: new ModuleFunctionShape(node, {
165
193
  name: node.getName() ?? 'functionModule',
166
- path: record.get('path').asString().getValue(),
194
+ path: path,
195
+ relativePath: `./${relativePath}`,
167
196
  isDefault: node.isDefaultExport(),
168
197
  }),
169
198
  }
@@ -194,6 +223,38 @@ function isValidRequireCall(callExpression: ts.CallExpression, requirePath: ts.S
194
223
  return isRequire && !isRelativePath
195
224
  }
196
225
 
226
+ function buildParentPathMap(dependencyNodes: DependencyNode[]) {
227
+ const importerMap = {}
228
+ for (const node of dependencyNodes) {
229
+ let parent = node.parentPackage
230
+
231
+ while (parent) {
232
+ const importerMapKey = `${node.pkgName}@${node.updatedManifest.version}`
233
+ if (!importerMap[importerMapKey]) {
234
+ importerMap[importerMapKey] = []
235
+ }
236
+ importerMap[importerMapKey].push(parent.pkgName)
237
+
238
+ const newParent = dependencyNodes.find((potentialParent) => {
239
+ if (!parent || !parent.pkgName) {
240
+ return false
241
+ }
242
+ if (potentialParent.updatedManifest.dependencies[parent!.pkgName]) {
243
+ return potentialParent
244
+ }
245
+ return false
246
+ })
247
+ parent = newParent
248
+ ? {
249
+ pkgName: newParent.updatedManifest.name,
250
+ version: newParent.updatedManifest.version,
251
+ }
252
+ : undefined
253
+ }
254
+ }
255
+ return importerMap
256
+ }
257
+
197
258
  class ModuleDependencyShape extends Shape {
198
259
  private readonly moduleName: string
199
260
 
@@ -214,7 +275,11 @@ class ModuleDependencyShape extends Shape {
214
275
  }
215
276
 
216
277
  // TODO: Need to have some invalidation mechanism. Maybe the plugin framework can provide plugins with a managed cache to use for stuff like this?
217
- const DEPENDENCY_CACHE: globalThis.Record<string, Result<ModuleDependencyShape>> = {}
278
+ let DEPENDENCY_CACHE: globalThis.Record<string, Result<ModuleDependencyShape>> = {}
279
+ // Expose cache clearing for tests
280
+ export function clearDependencyCache() {
281
+ DEPENDENCY_CACHE = {}
282
+ }
218
283
 
219
284
  function parseModuleDependency(
220
285
  node: ts.ImportDeclaration | ts.ExportDeclaration | ts.CallExpression
@@ -261,6 +326,41 @@ function generateSBOMContent(context: RecordContext) {
261
326
  return sbomBuilder.generateSBOM(context)
262
327
  }
263
328
 
329
+ function getModuleDependencyPath(
330
+ config: NowConfig,
331
+ module: { name: string; file: string; version: string; packageJson: Package; importerPath?: string[] }
332
+ ) {
333
+ const { name, file, packageJson, importerPath, version } = module
334
+
335
+ if (NowConfig.legacyPackageResolution(config)) {
336
+ return NowConfig.moduleResolutionPath(config, packageJson, true, name, version, file)
337
+ }
338
+
339
+ if (config.hoistDependencies) {
340
+ return NowConfig.moduleResolutionPath(config, packageJson, true, NODE_MODULES, name, file)
341
+ }
342
+
343
+ if (importerPath && importerPath.length > 0) {
344
+ const pathSegments = [...importerPath].reverse()
345
+ const pathSegmentsWithNodeModules: string[] = []
346
+ pathSegments.forEach((segment) => {
347
+ pathSegmentsWithNodeModules.push(NODE_MODULES)
348
+ pathSegmentsWithNodeModules.push(segment)
349
+ })
350
+ return NowConfig.moduleResolutionPath(
351
+ config,
352
+ packageJson,
353
+ true,
354
+ ...pathSegmentsWithNodeModules,
355
+ NODE_MODULES,
356
+ name,
357
+ file
358
+ )
359
+ }
360
+
361
+ return NowConfig.moduleResolutionPath(config, packageJson, true, NODE_MODULES, name, file)
362
+ }
363
+
264
364
  export const ServerModulePlugin = Plugin.create({
265
365
  name: 'ServerModulePlugin',
266
366
  files: [
@@ -291,6 +391,7 @@ export const ServerModulePlugin = Plugin.create({
291
391
  return {
292
392
  success: true,
293
393
  value: {
394
+ source: record,
294
395
  name: `sys_module_${record.getId().getValue()}.xml`,
295
396
  category: record.getInstallCategory(),
296
397
  content: `<?xml version="1.0"?>
@@ -315,7 +416,7 @@ export const ServerModulePlugin = Plugin.create({
315
416
  {
316
417
  shape: SourceFileShape,
317
418
  fileTypes: ['module'],
318
- toRecord(file, { factory, fs, diagnostics, project, config, packageJson, compiler }) {
419
+ async toRecord(file, { factory, fs, diagnostics, project, config, packageJson, compiler }) {
319
420
  const path = file.getPath()
320
421
  if (!path.startsWith(project.resolvePath(config.serverModulesDir))) {
321
422
  return { success: false }
@@ -340,11 +441,11 @@ export const ServerModulePlugin = Plugin.create({
340
441
  }
341
442
 
342
443
  const relativePath = pathModule.relative(project.getRootDir(), resolvedPath)
343
- const sysModulePath = pathModule.join(config.scope, packageJson.name, packageJson.version, relativePath)
444
+ const sysModulePath = NowConfig.moduleResolutionPath(config, packageJson, false, relativePath)
344
445
 
345
446
  return {
346
447
  success: true,
347
- value: factory.createRecord({
448
+ value: await factory.createRecord({
348
449
  source: file,
349
450
  table: 'sys_module',
350
451
  explicitId: relativePath.replaceAll(/[./\\]/g, '_'),
@@ -367,29 +468,33 @@ export const ServerModulePlugin = Plugin.create({
367
468
  // TODO: When managed cache is provided to plugins, cache dependencies that were already handled to avoid reprocessing
368
469
  async toRecord(shape, { packageJson, diagnostics, fs, logger, project, factory, config }) {
369
470
  const dependencies = packageJson.dependencies ?? {}
370
- const { name, entry } = validateAndGetModuleSpecifier(shape.getModuleName())
471
+ const { name: parentName, entry } = validateAndGetModuleSpecifier(shape.getModuleName())
371
472
 
372
- const version = dependencies[name]
473
+ const version = dependencies[parentName]
373
474
  if (!version) {
374
- diagnostics.error(shape, `Dependency ${name} is not found in package.json`)
475
+ diagnostics.error(shape, `Dependency ${parentName} is not found in package.json`)
375
476
  return { success: false }
376
477
  }
377
478
 
378
- const id = `${name}@${version}`
479
+ const id = `${parentName}@${version}`
379
480
  const repack = await RepackService.create(logger, fs, project.getRootDir())
380
481
  const dependencyNodes = await repack.execute({
381
482
  id,
382
483
  entry: entry ? [entry] : ['.'],
383
484
  })
384
-
385
485
  if (!dependencyNodes) {
386
486
  throw new Error(`Failed to build dependency ${id}`)
387
487
  }
388
488
 
489
+ let importerMap = {}
490
+ if (!config.hoistDependencies) {
491
+ importerMap = buildParentPathMap(dependencyNodes)
492
+ }
493
+
389
494
  const modules: { id: string; path: string; content: string }[] = []
390
495
  const { Lint } = await import('../repack/lint/index.js')
391
496
  for (const node of dependencyNodes) {
392
- const { packagePath, files, updatedManifest } = node
497
+ const { packagePath, files, updatedManifest, pkgName } = node
393
498
  const { name, version } = updatedManifest
394
499
 
395
500
  for (const file of files) {
@@ -404,28 +509,38 @@ export const ServerModulePlugin = Plugin.create({
404
509
 
405
510
  modules.push({
406
511
  id: `${name}@${version}/${file}`,
407
- path: pathModule.join(config.scope, name, version, file),
512
+ path: getModuleDependencyPath(config, {
513
+ name,
514
+ file,
515
+ version,
516
+ packageJson,
517
+ importerPath: importerMap[`${pkgName}@${version}`],
518
+ }),
408
519
  content: fileContent,
409
520
  })
410
521
  }
411
522
  }
412
523
 
413
- const [first, ...rest] = modules.map((m) => {
414
- return factory.createRecord({
415
- source: shape,
416
- table: 'sys_module',
417
- explicitId: m.id,
418
- properties: {
419
- path: m.path,
420
- content: Shape.from(shape, sanitizeModuleContent(m.content))
421
- .asString()
422
- .withContentType('cdata'),
423
- external_source: true,
424
- sys_name: m.path,
425
- },
426
- })
427
- })
524
+ const records: Record[] = []
525
+ for (const m of modules) {
526
+ records.push(
527
+ await factory.createRecord({
528
+ source: shape,
529
+ table: 'sys_module',
530
+ explicitId: m.id,
531
+ properties: {
532
+ path: m.path,
533
+ content: Shape.from(shape, sanitizeModuleContent(m.content))
534
+ .asString()
535
+ .withContentType('cdata'),
536
+ external_source: true,
537
+ sys_name: m.path,
538
+ },
539
+ })
540
+ )
541
+ }
428
542
 
543
+ const [first, ...rest] = records
429
544
  if (!first) {
430
545
  return { success: false }
431
546
  }
@@ -51,7 +51,7 @@ export const SPAngularProviderPlugin = Plugin.create({
51
51
  .filter((provider) => provider.equals(providerId))
52
52
  .forEach((provider) => diagnostics.error(provider, 'recursive dependency detected'))
53
53
 
54
- const providerRecord = factory.createRecord({
54
+ const providerRecord = await factory.createRecord({
55
55
  source: callExpression,
56
56
  table: 'sp_angular_provider',
57
57
  explicitId: providerObj.get('$id'),
@@ -65,16 +65,18 @@ export const SPAngularProviderPlugin = Plugin.create({
65
65
  return {
66
66
  success: true,
67
67
  value: providerRecord.with(
68
- ...requires.map((child) => {
69
- return factory.createRecord({
70
- source: callExpression,
71
- table: 'm2m_sp_ng_pro_sp_ng_pro',
72
- properties: {
73
- required_by: providerRecord.getId(),
74
- requires: child.ifString()?.getValue() ?? child.ifRecord()?.getId(),
75
- },
68
+ ...(await Promise.all(
69
+ requires.map(async (child) => {
70
+ return factory.createRecord({
71
+ source: callExpression,
72
+ table: 'm2m_sp_ng_pro_sp_ng_pro',
73
+ properties: {
74
+ required_by: providerRecord.getId(),
75
+ requires: child.ifString()?.getValue() ?? child.ifRecord()?.getId(),
76
+ },
77
+ })
76
78
  })
77
- })
79
+ ))
78
80
  ),
79
81
  }
80
82
  },
@@ -123,7 +123,7 @@ export const SPWidgetDependencyPlugin = Plugin.create({
123
123
 
124
124
  return {
125
125
  success: true,
126
- value: factory.createRecord({
126
+ value: await factory.createRecord({
127
127
  source: callExpression,
128
128
  table: 'sp_js_include',
129
129
  explicitId: jsIncludeId,
@@ -156,7 +156,7 @@ export const SPWidgetDependencyPlugin = Plugin.create({
156
156
 
157
157
  return {
158
158
  success: true,
159
- value: factory.createRecord({
159
+ value: await factory.createRecord({
160
160
  source: callExpression,
161
161
  table: 'sp_css_include',
162
162
  explicitId: cssIncludeId,
@@ -199,7 +199,7 @@ export const SPWidgetDependencyPlugin = Plugin.create({
199
199
  })
200
200
  .filter((guid) => guid) as string[]) || []
201
201
 
202
- const dependencyRecord = factory.createRecord({
202
+ const dependencyRecord = await factory.createRecord({
203
203
  source: callExpression,
204
204
  table: 'sp_dependency',
205
205
  explicitId: dependency.get('$id'),
@@ -211,7 +211,7 @@ export const SPWidgetDependencyPlugin = Plugin.create({
211
211
  })),
212
212
  })
213
213
 
214
- const cssIncludes = getIncludeRecords(
214
+ const cssIncludes = await getIncludeRecords(
215
215
  dependency.get('cssIncludes'),
216
216
  dependencyRecord.getId(),
217
217
  factory,
@@ -220,7 +220,7 @@ export const SPWidgetDependencyPlugin = Plugin.create({
220
220
  diagnostics
221
221
  )
222
222
 
223
- const jsIncludes = getIncludeRecords(
223
+ const jsIncludes = await getIncludeRecords(
224
224
  dependency.get('jsIncludes'),
225
225
  dependencyRecord.getId(),
226
226
  factory,
@@ -238,7 +238,7 @@ export const SPWidgetDependencyPlugin = Plugin.create({
238
238
  ],
239
239
  })
240
240
 
241
- function getIncludeRecords(
241
+ async function getIncludeRecords(
242
242
  shape: Shape,
243
243
  dependencyId: Shape,
244
244
  factory: Factory,
@@ -247,9 +247,8 @@ function getIncludeRecords(
247
247
  diagnostics: Diagnostics
248
248
  ) {
249
249
  return (
250
- (shape
251
- ?.ifArray()
252
- ?.map((include) => {
250
+ await Promise.all(
251
+ shape?.ifArray()?.map(async (include) => {
253
252
  const includeProps = include.ifObject()?.get('include')
254
253
 
255
254
  let includeId: string | RecordId
@@ -270,7 +269,7 @@ function getIncludeRecords(
270
269
  [includeTable]: includeId,
271
270
  sp_dependency: dependencyId,
272
271
  }
273
- return factory.createRecord({
272
+ return await factory.createRecord({
274
273
  source: shape,
275
274
  table: m2mTable,
276
275
  properties: {
@@ -278,7 +277,7 @@ function getIncludeRecords(
278
277
  ...m2mProps,
279
278
  },
280
279
  })
281
- })
282
- .filter((rec) => rec) as Record[]) || []
283
- )
280
+ }) ?? []
281
+ )
282
+ ).filter((rec) => rec) as Record[]
284
283
  }
@@ -165,7 +165,7 @@ export const SPWidgetPlugin = Plugin.create({
165
165
  (config.scope.startsWith('sn_') || config.scope.startsWith('snc_'))) ||
166
166
  false
167
167
 
168
- const widgetRecord = factory.createRecord({
168
+ const widgetRecord = await factory.createRecord({
169
169
  source: callExpression,
170
170
  table: 'sp_widget',
171
171
  explicitId: widget.get('$id'),
@@ -207,38 +207,44 @@ export const SPWidgetPlugin = Plugin.create({
207
207
  return {
208
208
  success: true,
209
209
  value: widgetRecord.with(
210
- ...templates.map((template: SPTemplate) => {
211
- return factory.createRecord({
212
- source: callExpression,
213
- table: 'sp_ng_template',
214
- explicitId: template.$id as string,
215
- properties: {
216
- id: template.id,
217
- sp_widget: widgetRecord.getId(),
218
- template: template.htmlTemplate,
219
- },
210
+ ...(await Promise.all(
211
+ templates.map(async (template: SPTemplate) => {
212
+ return await factory.createRecord({
213
+ source: callExpression,
214
+ table: 'sp_ng_template',
215
+ explicitId: template.$id as string,
216
+ properties: {
217
+ id: template.id,
218
+ sp_widget: widgetRecord.getId(),
219
+ template: template.htmlTemplate,
220
+ },
221
+ })
220
222
  })
221
- }),
222
- ...dependencies.map((dep) => {
223
- return factory.createRecord({
224
- source: callExpression,
225
- table: 'm2m_sp_widget_dependency',
226
- properties: {
227
- sp_dependency: dep!,
228
- sp_widget: widgetRecord.getId(),
229
- },
223
+ )),
224
+ ...(await Promise.all(
225
+ dependencies.map(async (dep) => {
226
+ return await factory.createRecord({
227
+ source: callExpression,
228
+ table: 'm2m_sp_widget_dependency',
229
+ properties: {
230
+ sp_dependency: dep!,
231
+ sp_widget: widgetRecord.getId(),
232
+ },
233
+ })
230
234
  })
231
- }),
232
- ...angularProviders.map((ap) => {
233
- return factory.createRecord({
234
- source: callExpression,
235
- table: 'm2m_sp_ng_pro_sp_widget',
236
- properties: {
237
- sp_angular_provider: ap!,
238
- sp_widget: widgetRecord.getId(),
239
- },
235
+ )),
236
+ ...(await Promise.all(
237
+ angularProviders.map(async (ap) => {
238
+ return await factory.createRecord({
239
+ source: callExpression,
240
+ table: 'm2m_sp_ng_pro_sp_widget',
241
+ properties: {
242
+ sp_angular_provider: ap!,
243
+ sp_widget: widgetRecord.getId(),
244
+ },
245
+ })
240
246
  })
241
- })
247
+ ))
242
248
  ),
243
249
  }
244
250
  },