@servicenow/sdk-build-plugins 4.1.1 → 4.2.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.
- package/dist/acl-plugin.js +13 -4
- package/dist/acl-plugin.js.map +1 -1
- package/dist/application-menu-plugin.js +1 -0
- package/dist/application-menu-plugin.js.map +1 -1
- package/dist/atf/step-configs.d.ts +13 -12
- package/dist/atf/step-configs.js.map +1 -1
- package/dist/atf/test-plugin.d.ts +1 -1
- package/dist/atf/test-plugin.js +8 -5
- package/dist/atf/test-plugin.js.map +1 -1
- package/dist/basic-syntax-plugin.js +51 -13
- package/dist/basic-syntax-plugin.js.map +1 -1
- package/dist/business-rule-plugin.js.map +1 -1
- package/dist/claims-plugin.js +1 -1
- package/dist/claims-plugin.js.map +1 -1
- package/dist/client-script-plugin.js +5 -17
- package/dist/client-script-plugin.js.map +1 -1
- package/dist/column/column-helper.d.ts +1 -1
- package/dist/column/column-helper.js +46 -2
- package/dist/column/column-helper.js.map +1 -1
- package/dist/column/column-to-record.js +6 -4
- package/dist/column/column-to-record.js.map +1 -1
- package/dist/column-plugin.js +106 -27
- package/dist/column-plugin.js.map +1 -1
- package/dist/data-plugin.d.ts +3 -0
- package/dist/data-plugin.js +208 -0
- package/dist/data-plugin.js.map +1 -0
- package/dist/import-sets-plugin.d.ts +2 -0
- package/dist/import-sets-plugin.js +412 -0
- package/dist/import-sets-plugin.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/json-plugin.d.ts +4 -4
- package/dist/json-plugin.js +21 -7
- package/dist/json-plugin.js.map +1 -1
- package/dist/list-plugin.js +83 -1
- package/dist/list-plugin.js.map +1 -1
- package/dist/now-attach-plugin.d.ts +35 -0
- package/dist/now-attach-plugin.js +317 -0
- package/dist/now-attach-plugin.js.map +1 -0
- package/dist/now-config-plugin.js +3 -0
- package/dist/now-config-plugin.js.map +1 -1
- package/dist/now-include-plugin.js +7 -1
- package/dist/now-include-plugin.js.map +1 -1
- package/dist/package-json-plugin.js +2 -2
- package/dist/package-json-plugin.js.map +1 -1
- package/dist/record-plugin.d.ts +6 -0
- package/dist/record-plugin.js +50 -23
- package/dist/record-plugin.js.map +1 -1
- package/dist/repack/lint/Rules.js.map +1 -1
- package/dist/rest-api-plugin.js +28 -31
- package/dist/rest-api-plugin.js.map +1 -1
- package/dist/role-plugin.js +1 -0
- package/dist/role-plugin.js.map +1 -1
- package/dist/server-module-plugin/index.js +15 -2
- package/dist/server-module-plugin/index.js.map +1 -1
- package/dist/service-portal/widget-plugin.js +4 -1
- package/dist/service-portal/widget-plugin.js.map +1 -1
- package/dist/static-content-plugin.d.ts +1 -0
- package/dist/static-content-plugin.js +4 -3
- package/dist/static-content-plugin.js.map +1 -1
- package/dist/table-plugin.js +33 -2
- package/dist/table-plugin.js.map +1 -1
- package/dist/ui-page-plugin.js +2 -1
- package/dist/ui-page-plugin.js.map +1 -1
- package/dist/ui-policy-plugin.d.ts +2 -0
- package/dist/ui-policy-plugin.js +407 -0
- package/dist/ui-policy-plugin.js.map +1 -0
- package/dist/utils.d.ts +10 -1
- package/dist/utils.js +24 -0
- package/dist/utils.js.map +1 -1
- package/dist/view-plugin.js +1 -1
- package/dist/view-plugin.js.map +1 -1
- package/package.json +6 -6
- package/src/_types/eslint-plugin-es-x.d.ts +17 -0
- package/src/_types/md5.js.d.ts +8 -0
- package/src/acl-plugin.ts +19 -9
- package/src/application-menu-plugin.ts +1 -0
- package/src/atf/step-configs.ts +14 -12
- package/src/atf/test-plugin.ts +40 -21
- package/src/basic-syntax-plugin.ts +61 -13
- package/src/business-rule-plugin.ts +7 -4
- package/src/claims-plugin.ts +1 -1
- package/src/client-script-plugin.ts +8 -22
- package/src/column/column-helper.ts +65 -3
- package/src/column/column-to-record.ts +6 -4
- package/src/column-plugin.ts +141 -39
- package/src/data-plugin.ts +266 -0
- package/src/import-sets-plugin.ts +542 -0
- package/src/index.ts +4 -0
- package/src/json-plugin.ts +31 -12
- package/src/list-plugin.ts +91 -1
- package/src/now-attach-plugin.ts +399 -0
- package/src/now-config-plugin.ts +6 -2
- package/src/now-include-plugin.ts +8 -1
- package/src/package-json-plugin.ts +3 -3
- package/src/record-plugin.ts +61 -30
- package/src/repack/lint/Rules.ts +1 -10
- package/src/rest-api-plugin.ts +45 -51
- package/src/role-plugin.ts +1 -0
- package/src/server-module-plugin/index.ts +21 -5
- package/src/service-portal/widget-plugin.ts +4 -1
- package/src/static-content-plugin.ts +2 -2
- package/src/table-plugin.ts +47 -7
- package/src/ui-page-plugin.ts +2 -1
- package/src/ui-policy-plugin.ts +509 -0
- package/src/utils.ts +27 -1
- package/src/view-plugin.ts +1 -1
package/src/acl-plugin.ts
CHANGED
|
@@ -54,7 +54,7 @@ export const AclPlugin = Plugin.create({
|
|
|
54
54
|
},
|
|
55
55
|
},
|
|
56
56
|
toShape(record, { descendants }) {
|
|
57
|
-
const type = reverseLookup(AclTypes, record.get('type').getValue()) || record.get('type')
|
|
57
|
+
const type = reverseLookup(AclTypes, record.get('type').getValue() as string) || record.get('type')
|
|
58
58
|
const roles = descendants.query('sys_security_acl_role').map((m2m) => m2m.get('sys_user_role'))
|
|
59
59
|
|
|
60
60
|
return {
|
|
@@ -75,14 +75,14 @@ export const AclPlugin = Plugin.create({
|
|
|
75
75
|
appliesTo: $.from('applies_to').def(''),
|
|
76
76
|
type: $.val(type),
|
|
77
77
|
securityAttribute: $.from('security_attribute')
|
|
78
|
-
.map((v) => reverseLookup(AclAttributes, v.getValue()) || v)
|
|
78
|
+
.map((v) => reverseLookup(AclAttributes, v.getValue() as string) || v)
|
|
79
79
|
.def(''),
|
|
80
|
-
operation: $.map((v) => reverseLookup(AclOperations, v.getValue()) || v),
|
|
80
|
+
operation: $.map((v) => reverseLookup(AclOperations, v.getValue() as string) || v),
|
|
81
81
|
script: $.map((v) => v.ifString()?.getValue()).def(''),
|
|
82
82
|
roles: $.val(roles.length > 0 ? roles : undefined),
|
|
83
83
|
[merge]: $.from('type', 'name').map((type, name) =>
|
|
84
84
|
getTableOrName(
|
|
85
|
-
type.pipe((t) => reverseLookup(AclTypes, t.getValue())),
|
|
85
|
+
type.pipe((t) => reverseLookup(AclTypes, t.getValue() as string)),
|
|
86
86
|
name.asString().getValue()
|
|
87
87
|
)
|
|
88
88
|
),
|
|
@@ -159,8 +159,14 @@ export const AclPlugin = Plugin.create({
|
|
|
159
159
|
name: $.from('name', 'table', 'field').map(
|
|
160
160
|
(n, t, f) => n.ifString() ?? (f.ifString() ? `${t.getValue()}.${f.getValue()}` : t)
|
|
161
161
|
),
|
|
162
|
-
type: $.map((type) =>
|
|
163
|
-
|
|
162
|
+
type: $.map((type) => {
|
|
163
|
+
const typeKey = type.asString().getValue()
|
|
164
|
+
return AclTypes[typeKey as keyof typeof AclTypes] ?? type
|
|
165
|
+
}),
|
|
166
|
+
operation: $.map((op) => {
|
|
167
|
+
const opKey = op.asString().getValue()
|
|
168
|
+
return AclOperations[opKey as keyof typeof AclOperations] ?? op
|
|
169
|
+
}),
|
|
164
170
|
advanced: $.val(advanced),
|
|
165
171
|
script: $.map(
|
|
166
172
|
(v) =>
|
|
@@ -168,7 +174,11 @@ export const AclPlugin = Plugin.create({
|
|
|
168
174
|
v
|
|
169
175
|
).toCdata(),
|
|
170
176
|
security_attribute: $.from('securityAttribute').map(
|
|
171
|
-
(v) =>
|
|
177
|
+
(v) =>
|
|
178
|
+
v.ifString()?.pipe((v) => {
|
|
179
|
+
const attrKey = v.getValue()
|
|
180
|
+
return AclAttributes[attrKey as keyof typeof AclAttributes]
|
|
181
|
+
}) ?? v
|
|
172
182
|
),
|
|
173
183
|
})),
|
|
174
184
|
})
|
|
@@ -243,7 +253,7 @@ export const AclPlugin = Plugin.create({
|
|
|
243
253
|
})
|
|
244
254
|
|
|
245
255
|
function getTableOrName(type: keyof typeof AclTypes, name: string) {
|
|
246
|
-
if (AclNamedTypes
|
|
256
|
+
if (type in AclNamedTypes) {
|
|
247
257
|
return { name }
|
|
248
258
|
}
|
|
249
259
|
const split = name.indexOf('.')
|
|
@@ -253,7 +263,7 @@ function getTableOrName(type: keyof typeof AclTypes, name: string) {
|
|
|
253
263
|
return { table, ...(field ? { field } : {}) }
|
|
254
264
|
}
|
|
255
265
|
|
|
256
|
-
function reverseLookup<T extends object>(obj: T, sysId): keyof T {
|
|
266
|
+
function reverseLookup<T extends object>(obj: T, sysId: string): keyof T {
|
|
257
267
|
return (Object.entries(obj)
|
|
258
268
|
.filter(([_, id]) => id === sysId)
|
|
259
269
|
.map(([key]) => key)[0] || '') as keyof T
|
|
@@ -51,6 +51,7 @@ export const ApplicationMenuPlugin = Plugin.create({
|
|
|
51
51
|
value: new CallExpressionShape({
|
|
52
52
|
source: record,
|
|
53
53
|
callee: 'ApplicationMenu',
|
|
54
|
+
exportName: record.get('sys_name')?.ifString()?.getValue(),
|
|
54
55
|
args: [
|
|
55
56
|
record.transform(({ $ }) => ({
|
|
56
57
|
$id: $.val(NowIdShape.from(record)),
|
package/src/atf/step-configs.ts
CHANGED
|
@@ -5,28 +5,30 @@ export type ATFVariableInfo = {
|
|
|
5
5
|
inputVariableId: string
|
|
6
6
|
type: string
|
|
7
7
|
order: number
|
|
8
|
-
default?:
|
|
8
|
+
default?: unknown
|
|
9
9
|
mandatory?: boolean
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export type Category = keyof ATFType
|
|
13
13
|
|
|
14
|
-
type FunctionParameters<F> = F extends (inputs: infer P) =>
|
|
14
|
+
type FunctionParameters<F> = F extends (inputs: infer P) => unknown
|
|
15
15
|
? P extends object
|
|
16
16
|
? Exclude<keyof P, keyof StandardStepValues>
|
|
17
17
|
: never
|
|
18
18
|
: never
|
|
19
19
|
|
|
20
|
-
type
|
|
20
|
+
export type StepMetadata<T extends FunctionParameters<unknown> = FunctionParameters<unknown>> = {
|
|
21
|
+
name: string
|
|
22
|
+
stepConfigId: string
|
|
23
|
+
variables: {
|
|
24
|
+
[K in T]: ATFVariableInfo
|
|
25
|
+
}
|
|
26
|
+
defaultTimeout?: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type ToRecordStepMetadata = {
|
|
21
30
|
[C in keyof ATFType]: {
|
|
22
|
-
[FunctionName in keyof ATFType[C]]:
|
|
23
|
-
name: string
|
|
24
|
-
stepConfigId: string
|
|
25
|
-
variables: {
|
|
26
|
-
[K in FunctionParameters<ATFType[C][FunctionName]>]: ATFVariableInfo
|
|
27
|
-
}
|
|
28
|
-
defaultTimeout?: string
|
|
29
|
-
}
|
|
31
|
+
[FunctionName in keyof ATFType[C]]: StepMetadata<FunctionParameters<ATFType[C][FunctionName]>>
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
|
|
@@ -2355,7 +2357,7 @@ export type ToShapeStepMetadata = Record<
|
|
|
2355
2357
|
field: string
|
|
2356
2358
|
type: string
|
|
2357
2359
|
mandatory: boolean
|
|
2358
|
-
default?:
|
|
2360
|
+
default?: unknown
|
|
2359
2361
|
}
|
|
2360
2362
|
>
|
|
2361
2363
|
}
|
package/src/atf/test-plugin.ts
CHANGED
|
@@ -20,9 +20,15 @@ import { NowIdShape } from '../now-id-plugin'
|
|
|
20
20
|
import { ArrowFunctionShape } from '../arrow-function-plugin'
|
|
21
21
|
import { create } from 'xmlbuilder2'
|
|
22
22
|
import { Test } from '@servicenow/sdk-core/runtime/app'
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
type ATFVariableInfo,
|
|
25
|
+
type Category,
|
|
26
|
+
ToShapeStepConfigs,
|
|
27
|
+
ToRecordStepConfigs,
|
|
28
|
+
type StepMetadata,
|
|
29
|
+
} from './step-configs'
|
|
24
30
|
import { durationFieldToXML, formatDateToPlatformFormat, parseGlideDuration } from '@servicenow/sdk-build-core'
|
|
25
|
-
import type {
|
|
31
|
+
import type { Duration } from '@servicenow/sdk/core'
|
|
26
32
|
|
|
27
33
|
export const TestPlugin = Plugin.create({
|
|
28
34
|
name: 'TestPlugin',
|
|
@@ -381,7 +387,7 @@ function getFieldValuesFromElementMappingRecords(elementMappingRecords: RecordSh
|
|
|
381
387
|
}
|
|
382
388
|
|
|
383
389
|
function convertTimeoutToSystemFormat(timeoutShape: Shape) {
|
|
384
|
-
const timeoutDuration = timeoutShape.ifObject()?.getValue() as
|
|
390
|
+
const timeoutDuration = timeoutShape.ifObject()?.getValue() as Duration | undefined
|
|
385
391
|
const timeoutDate = timeoutDuration && durationFieldToXML(timeoutDuration)
|
|
386
392
|
return timeoutDate && formatDateToPlatformFormat(timeoutDate)
|
|
387
393
|
}
|
|
@@ -389,8 +395,9 @@ function convertTimeoutToSystemFormat(timeoutShape: Shape) {
|
|
|
389
395
|
function anyStepsAreUnknown(stepRecords: RecordShape[], testName: string) {
|
|
390
396
|
return stepRecords.some((stepRecord) => {
|
|
391
397
|
const stepConfigId = stepRecord.get('step_config').toString().getValue()
|
|
392
|
-
if (!ToShapeStepConfigs[stepConfigId]) {
|
|
393
|
-
const stepConfigName =
|
|
398
|
+
if (!ToShapeStepConfigs[stepConfigId as keyof typeof ToShapeStepConfigs]) {
|
|
399
|
+
const stepConfigName =
|
|
400
|
+
UNSUPPORTED_STEP_CONFIGS[stepConfigId as keyof typeof UNSUPPORTED_STEP_CONFIGS] ?? stepConfigId
|
|
394
401
|
console.error(
|
|
395
402
|
`Unable to transform ATF test '${testName}' because of unsupported step_config: '${stepConfigName}'`
|
|
396
403
|
)
|
|
@@ -436,7 +443,11 @@ function propertyAccessToGemExpression(
|
|
|
436
443
|
return `{{step['${stepId}']${suffix}}}`
|
|
437
444
|
}
|
|
438
445
|
|
|
439
|
-
function createGemExpressionsFromShape(
|
|
446
|
+
function createGemExpressionsFromShape(
|
|
447
|
+
shape: Shape,
|
|
448
|
+
stepRecords: RecordShape[],
|
|
449
|
+
diagnostics: Diagnostics
|
|
450
|
+
): string | Record<string, unknown> | undefined {
|
|
440
451
|
if (shape instanceof PropertyAccessShape) {
|
|
441
452
|
return propertyAccessToGemExpression(shape, stepRecords, diagnostics)
|
|
442
453
|
}
|
|
@@ -452,7 +463,7 @@ function createGemExpressionsFromShape(shape: Shape, stepRecords: RecordShape[],
|
|
|
452
463
|
}
|
|
453
464
|
|
|
454
465
|
if (shape instanceof ObjectShape) {
|
|
455
|
-
const obj = {}
|
|
466
|
+
const obj: Record<string, unknown> = {}
|
|
456
467
|
let gemExpressionFound = false
|
|
457
468
|
for (const key in shape.properties()) {
|
|
458
469
|
const value = createGemExpressionsFromShape(shape.get(key, false), stepRecords, diagnostics)
|
|
@@ -499,23 +510,26 @@ function getStepInfoFromAtfCallExpression(
|
|
|
499
510
|
return undefined
|
|
500
511
|
}
|
|
501
512
|
|
|
502
|
-
const [, category, funcName] = callExpression.getCallee().split('.')
|
|
513
|
+
const [, category, funcName] = callExpression.getCallee().split('.') as [never, Category?, string?]
|
|
514
|
+
|
|
503
515
|
if (!category || !funcName) {
|
|
504
516
|
diagnostics.info(callExpression, 'Invalid ATF step')
|
|
505
517
|
return undefined
|
|
506
518
|
}
|
|
507
519
|
|
|
508
|
-
|
|
520
|
+
const categoryKey = category
|
|
521
|
+
if (!ToRecordStepConfigs[categoryKey]) {
|
|
509
522
|
diagnostics.warn(callExpression, `Unknown category: ${category}`)
|
|
510
523
|
return undefined
|
|
511
524
|
}
|
|
512
525
|
|
|
513
|
-
|
|
526
|
+
const categorySteps = ToRecordStepConfigs[categoryKey]
|
|
527
|
+
if (!(funcName in categorySteps)) {
|
|
514
528
|
diagnostics.warn(callExpression, `Unknown step: ${funcName}`)
|
|
515
529
|
return undefined
|
|
516
530
|
}
|
|
517
531
|
|
|
518
|
-
const stepConfig =
|
|
532
|
+
const stepConfig = categorySteps[funcName as keyof typeof categorySteps] as StepMetadata
|
|
519
533
|
const values = callExpression.getArgument(0).asObject()
|
|
520
534
|
return {
|
|
521
535
|
displayName: stepConfig.name,
|
|
@@ -524,7 +538,7 @@ function getStepInfoFromAtfCallExpression(
|
|
|
524
538
|
table: values.get('table')?.ifString(),
|
|
525
539
|
source: callExpression,
|
|
526
540
|
identifier,
|
|
527
|
-
defaultTimeout: stepConfig.defaultTimeout,
|
|
541
|
+
defaultTimeout: stepConfig.defaultTimeout as string,
|
|
528
542
|
values,
|
|
529
543
|
}
|
|
530
544
|
}
|
|
@@ -566,14 +580,19 @@ function variableElementPathToPropertyAccess(source: Source, propertyAccessPath:
|
|
|
566
580
|
})
|
|
567
581
|
}
|
|
568
582
|
|
|
569
|
-
function getElementMappingValues(
|
|
583
|
+
function getElementMappingValues(
|
|
584
|
+
source: Source,
|
|
585
|
+
value: unknown,
|
|
586
|
+
stepIdToVarName: Map<string, string>
|
|
587
|
+
): object | object[] | string | undefined {
|
|
570
588
|
if (typeof value === 'object' && value !== null) {
|
|
571
589
|
if (Array.isArray(value)) {
|
|
572
590
|
return value.map((v) => getElementMappingValues(source, v, stepIdToVarName))
|
|
573
591
|
} else {
|
|
574
|
-
const obj = {}
|
|
575
|
-
|
|
576
|
-
|
|
592
|
+
const obj: Record<string, unknown> = {}
|
|
593
|
+
const valueObj = value
|
|
594
|
+
for (const key in valueObj) {
|
|
595
|
+
obj[key] = getElementMappingValues(source, valueObj[key as keyof typeof valueObj], stepIdToVarName)
|
|
577
596
|
}
|
|
578
597
|
return obj
|
|
579
598
|
}
|
|
@@ -581,13 +600,13 @@ function getElementMappingValues(source: Source, value: any, stepIdToVarName: Ma
|
|
|
581
600
|
|
|
582
601
|
const potentialGemExpression = typeof value === 'string' ? value : undefined
|
|
583
602
|
if (!potentialGemExpression) {
|
|
584
|
-
return value
|
|
603
|
+
return value as string
|
|
585
604
|
}
|
|
586
605
|
|
|
587
606
|
const [matched] = Array.from(potentialGemExpression.matchAll(GemRegex))
|
|
588
607
|
const simpleGemExpression = matched && matched[0] === potentialGemExpression
|
|
589
608
|
if (!matched) {
|
|
590
|
-
return value
|
|
609
|
+
return value as string
|
|
591
610
|
}
|
|
592
611
|
|
|
593
612
|
// If the GEM expression is simple, it only contains the GEM
|
|
@@ -643,7 +662,7 @@ function getElementMappingValues(source: Source, value: any, stepIdToVarName: Ma
|
|
|
643
662
|
})
|
|
644
663
|
}
|
|
645
664
|
|
|
646
|
-
function objectToEncodedQuery(objectShape: Record<string,
|
|
665
|
+
function objectToEncodedQuery(objectShape: Record<string, object | string | number | boolean>) {
|
|
647
666
|
return Object.entries(objectShape)
|
|
648
667
|
.map(([key, value]) => {
|
|
649
668
|
const escapedValue = value.toString().replaceAll('^', '^^')
|
|
@@ -653,7 +672,7 @@ function objectToEncodedQuery(objectShape: Record<string, any>) {
|
|
|
653
672
|
.join('^')
|
|
654
673
|
}
|
|
655
674
|
|
|
656
|
-
export function serializeValueToRecord(value:
|
|
675
|
+
export function serializeValueToRecord(value: unknown, type: string, defaultValue: unknown) {
|
|
657
676
|
value = value === undefined ? defaultValue : value
|
|
658
677
|
|
|
659
678
|
switch (type) {
|
|
@@ -670,7 +689,7 @@ export function serializeValueToRecord(value: any, type: string, defaultValue: a
|
|
|
670
689
|
return JSON.stringify(value)
|
|
671
690
|
}
|
|
672
691
|
case 'template_value':
|
|
673
|
-
return value && objectToEncodedQuery(value)
|
|
692
|
+
return value && objectToEncodedQuery(value as Record<string, object | string | number | boolean>)
|
|
674
693
|
case 'boolean':
|
|
675
694
|
return value ? 1 : 0
|
|
676
695
|
default:
|
|
@@ -24,7 +24,11 @@ import {
|
|
|
24
24
|
remove,
|
|
25
25
|
isFluentFile,
|
|
26
26
|
path as pathModule,
|
|
27
|
+
Record as DBRecord,
|
|
28
|
+
asDataHelper,
|
|
27
29
|
} from '@servicenow/sdk-build-core'
|
|
30
|
+
import { isDataHelper } from './data-plugin'
|
|
31
|
+
import { getCallExpressionName } from './utils'
|
|
28
32
|
|
|
29
33
|
export const BasicSyntaxPlugin = Plugin.create({
|
|
30
34
|
name: 'BasicSyntaxPlugin',
|
|
@@ -70,8 +74,26 @@ export const BasicSyntaxPlugin = Plugin.create({
|
|
|
70
74
|
return { success: false }
|
|
71
75
|
}
|
|
72
76
|
|
|
73
|
-
const
|
|
74
|
-
const
|
|
77
|
+
const { generatedDir, taxonomy } = config
|
|
78
|
+
const tableName =
|
|
79
|
+
shape.getSource() instanceof DBRecord ? (shape.getSource() as DBRecord).getTable() : undefined
|
|
80
|
+
|
|
81
|
+
const dir =
|
|
82
|
+
tableName && taxonomy.mapping[tableName]
|
|
83
|
+
? pathModule.join(generatedDir, taxonomy.mapping[tableName])
|
|
84
|
+
: generatedDir
|
|
85
|
+
|
|
86
|
+
let name = pathModule.basename(source.path).replace(RegExp(`${pathModule.extname(source.path)}$`), '')
|
|
87
|
+
if (project.isTypesGenerationMode()) {
|
|
88
|
+
// In types generation mode, use the exported variable name as the file name
|
|
89
|
+
// Scope directory is already set via per-scope Project rootDir
|
|
90
|
+
if (shape.is(VariableStatementShape) && shape.isExported()) {
|
|
91
|
+
name = shape.getVariableName().getName()
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const file = compiler.getOrCreateSourceFile(
|
|
95
|
+
project.resolvePath(project.getRootDir(), dir, `${name}.now.ts`)
|
|
96
|
+
)
|
|
75
97
|
const statement = project
|
|
76
98
|
.addFile(file.getFilePath(), { resolveDependencies: false })
|
|
77
99
|
.addStatement(shape.getCode())
|
|
@@ -167,6 +189,16 @@ export const BasicSyntaxPlugin = Plugin.create({
|
|
|
167
189
|
// Turn the number back into a string and compare with the original string to avoid
|
|
168
190
|
// lossy conversions due to floating point precision or other factors
|
|
169
191
|
return number.getValue().toString() === shape.getValue() ? number : undefined
|
|
192
|
+
} else if (isDataHelper(target)) {
|
|
193
|
+
if (!ts.Node.isCallExpression(target)) {
|
|
194
|
+
return undefined
|
|
195
|
+
}
|
|
196
|
+
const helperName = getCallExpressionName(target)
|
|
197
|
+
const timeZone = target
|
|
198
|
+
.getArguments()[1]
|
|
199
|
+
?.asKind(ts.SyntaxKind.StringLiteral)
|
|
200
|
+
?.getLiteralValue()
|
|
201
|
+
return asDataHelper(helperName, shape, timeZone)
|
|
170
202
|
} else {
|
|
171
203
|
return undefined
|
|
172
204
|
}
|
|
@@ -272,7 +304,7 @@ export const BasicSyntaxPlugin = Plugin.create({
|
|
|
272
304
|
const existingPropKey = [...shape.getAliases(name), name].find((aliasedKey) =>
|
|
273
305
|
existingNames.has(aliasedKey)
|
|
274
306
|
)
|
|
275
|
-
if (existingPropKey) {
|
|
307
|
+
if (existingPropKey !== undefined) {
|
|
276
308
|
if (existingPropKey !== name) {
|
|
277
309
|
target
|
|
278
310
|
.getPropertyOrThrow(existingPropKey)
|
|
@@ -280,6 +312,7 @@ export const BasicSyntaxPlugin = Plugin.create({
|
|
|
280
312
|
.getNameNode()
|
|
281
313
|
.replaceWithText(name)
|
|
282
314
|
}
|
|
315
|
+
|
|
283
316
|
await commit(value, existingNames.get(existingPropKey) as ts.Expression)
|
|
284
317
|
} else if (!value.equals(shape.getDefault(name))) {
|
|
285
318
|
propsToAdd.push({
|
|
@@ -318,35 +351,50 @@ export const BasicSyntaxPlugin = Plugin.create({
|
|
|
318
351
|
{
|
|
319
352
|
shape: VariableStatementShape,
|
|
320
353
|
async commit(shape, target, { commit }) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
if (ts.Node.isCallExpression(target) && parentStatement) {
|
|
324
|
-
parentStatement.replaceWithText(shape.getCode())
|
|
325
|
-
return { success: true }
|
|
326
|
-
}
|
|
354
|
+
// If target is ExpressionStatement, replace it directly
|
|
355
|
+
if (ts.Node.isExpressionStatement(target)) {
|
|
327
356
|
target.replaceWithText(shape.getCode())
|
|
328
357
|
return { success: true }
|
|
329
358
|
}
|
|
330
359
|
|
|
331
|
-
|
|
332
|
-
|
|
360
|
+
// If target is CallExpression, check parent type
|
|
361
|
+
if (ts.Node.isCallExpression(target)) {
|
|
362
|
+
const expressionStatement = target.getParentIfKind(ts.SyntaxKind.ExpressionStatement)
|
|
363
|
+
if (expressionStatement) {
|
|
364
|
+
expressionStatement.replaceWithText(shape.getCode())
|
|
365
|
+
return { success: true }
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Get VariableStatement for in-place updates (either from CallExpression ancestor or target itself)
|
|
370
|
+
const variableStatement = ts.Node.isVariableStatement(target)
|
|
371
|
+
? target
|
|
372
|
+
: target.getFirstAncestorByKindOrThrow(ts.SyntaxKind.VariableStatement)
|
|
373
|
+
|
|
374
|
+
// Update export modifier if needed
|
|
375
|
+
if (variableStatement.isExported() !== shape.isExported()) {
|
|
376
|
+
variableStatement.setIsExported(shape.isExported())
|
|
333
377
|
}
|
|
334
378
|
|
|
335
|
-
|
|
379
|
+
// Get the variable declaration
|
|
380
|
+
const [declaration, otherDeclaration] = variableStatement.getDeclarations()
|
|
336
381
|
if (!declaration) {
|
|
337
|
-
throw new Error(`Variable statement is missing a declaration: ${
|
|
382
|
+
throw new Error(`Variable statement is missing a declaration: ${variableStatement.getFullText()}`)
|
|
338
383
|
}
|
|
339
384
|
|
|
385
|
+
// Remove duplicate declarations
|
|
340
386
|
if (otherDeclaration) {
|
|
341
387
|
removeReferences(otherDeclaration)
|
|
342
388
|
remove(otherDeclaration)
|
|
343
389
|
}
|
|
344
390
|
|
|
391
|
+
// Update variable name if changed
|
|
345
392
|
const variableName = shape.getVariableName()
|
|
346
393
|
if (declaration.getName() !== variableName.getName()) {
|
|
347
394
|
await commit(variableName, declaration.getNameNode())
|
|
348
395
|
}
|
|
349
396
|
|
|
397
|
+
// Update initializer
|
|
350
398
|
await commit(shape.getInitializer(), declaration.getInitializerOrThrow())
|
|
351
399
|
return { success: true }
|
|
352
400
|
},
|
|
@@ -7,10 +7,13 @@ import { NowIncludeShape } from './now-include-plugin'
|
|
|
7
7
|
// Similar to lodash's groupBy, but simply stores the last element of each group
|
|
8
8
|
function groupByExistence<T>(collection: T[] | undefined, keyProvider: (element: T) => string): { [key: string]: T } {
|
|
9
9
|
return (
|
|
10
|
-
collection?.reduce(
|
|
11
|
-
groups
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
collection?.reduce(
|
|
11
|
+
(groups, e) => {
|
|
12
|
+
groups[keyProvider(e)] = e
|
|
13
|
+
return groups
|
|
14
|
+
},
|
|
15
|
+
{} as { [key: string]: T }
|
|
16
|
+
) ?? {}
|
|
14
17
|
)
|
|
15
18
|
}
|
|
16
19
|
|
package/src/claims-plugin.ts
CHANGED
|
@@ -59,7 +59,7 @@ export const ClaimsPlugin = Plugin.create({
|
|
|
59
59
|
return { success: false }
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
const allClaims = file.getJson()
|
|
62
|
+
const allClaims = file.getJson().asObject()
|
|
63
63
|
const records: Record[] = []
|
|
64
64
|
for (const [updateName, claims] of allClaims.entries()) {
|
|
65
65
|
for (const claim of claims
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CallExpressionShape, Plugin } from '@servicenow/sdk-build-core'
|
|
2
2
|
import { NowIdShape } from './now-id-plugin'
|
|
3
|
-
import { generateDeprecatedDiagnostics } from './utils'
|
|
3
|
+
import { generateDeprecatedDiagnostics, validateClientSideScript } from './utils'
|
|
4
|
+
import { NowIncludeShape } from './now-include-plugin'
|
|
4
5
|
|
|
5
6
|
enum UITypeMapping {
|
|
6
7
|
desktop = 0,
|
|
@@ -45,7 +46,8 @@ export const ClientScriptPlugin = Plugin.create({
|
|
|
45
46
|
name: 'ClientScriptPlugin',
|
|
46
47
|
records: {
|
|
47
48
|
sys_script_client: {
|
|
48
|
-
toShape(record) {
|
|
49
|
+
async toShape(record, { transform }) {
|
|
50
|
+
const script = await NowIncludeShape.fromRecord(record, record.get('script'), transform)
|
|
49
51
|
return {
|
|
50
52
|
success: true,
|
|
51
53
|
value: new CallExpressionShape({
|
|
@@ -59,7 +61,7 @@ export const ClientScriptPlugin = Plugin.create({
|
|
|
59
61
|
table: $,
|
|
60
62
|
appliesExtended: $.from('applies_extended').toBoolean().def(false),
|
|
61
63
|
isolateScript: $.from('isolate_script').toBoolean().def(false),
|
|
62
|
-
script:
|
|
64
|
+
script: $.val(script),
|
|
63
65
|
name: $,
|
|
64
66
|
description: $.def(''),
|
|
65
67
|
messages: $.def(''),
|
|
@@ -110,7 +112,7 @@ export const ClientScriptPlugin = Plugin.create({
|
|
|
110
112
|
)
|
|
111
113
|
}
|
|
112
114
|
|
|
113
|
-
if (script && !
|
|
115
|
+
if (script && !validateClientSideScript(script, compiler)) {
|
|
114
116
|
diagnostics.error(
|
|
115
117
|
clientScript.get('script'),
|
|
116
118
|
`Client side scripts cannot import or require modules.`
|
|
@@ -147,17 +149,6 @@ export const ClientScriptPlugin = Plugin.create({
|
|
|
147
149
|
],
|
|
148
150
|
})
|
|
149
151
|
|
|
150
|
-
function validateClientSideScripts(script: string, compiler: Compiler) {
|
|
151
|
-
const source = compiler.createSourceFile('tmp-file.ts', script)
|
|
152
|
-
const importDeclarations = source.getDescendantsOfKind(ts.SyntaxKind.ImportDeclaration)
|
|
153
|
-
const requireCalls = source.getDescendantsOfKind(ts.SyntaxKind.CallExpression).filter((callExpression) => {
|
|
154
|
-
return isRequire(callExpression)
|
|
155
|
-
})
|
|
156
|
-
const isValid = !(importDeclarations.length > 0 || requireCalls.length > 0)
|
|
157
|
-
compiler.removeSourceFile(source)
|
|
158
|
-
return isValid
|
|
159
|
-
}
|
|
160
|
-
|
|
161
152
|
function getUITypeFromId(id: number) {
|
|
162
153
|
const type = UITypeMapping[id]
|
|
163
154
|
if (!type) {
|
|
@@ -168,12 +159,7 @@ function getUITypeFromId(id: number) {
|
|
|
168
159
|
|
|
169
160
|
function getUITypeId(value: string) {
|
|
170
161
|
if (value in UITypeMapping) {
|
|
171
|
-
return UITypeMapping[value]
|
|
162
|
+
return UITypeMapping[value as keyof typeof UITypeMapping]
|
|
172
163
|
}
|
|
173
164
|
throw Error('Invalid ui_type found in xml')
|
|
174
165
|
}
|
|
175
|
-
|
|
176
|
-
function isRequire(callExpression: ts.CallExpression): boolean {
|
|
177
|
-
const expression = callExpression.getExpression()
|
|
178
|
-
return ts.Node.isIdentifier(expression) && expression.getText() === 'require'
|
|
179
|
-
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CallExpressionShape, Shape } from '@servicenow/sdk-build-core'
|
|
2
2
|
import {
|
|
3
|
+
ApprovalRulesColumn,
|
|
3
4
|
BasicDateTimeColumn,
|
|
4
5
|
BasicImageColumn,
|
|
5
6
|
BooleanColumn,
|
|
@@ -8,25 +9,42 @@ import {
|
|
|
8
9
|
ConditionsColumn,
|
|
9
10
|
DateColumn,
|
|
10
11
|
DateTimeColumn,
|
|
12
|
+
DayOfWeekColumn,
|
|
13
|
+
DaysOfWeekColumn,
|
|
11
14
|
DecimalColumn,
|
|
12
15
|
DocumentIdColumn,
|
|
13
16
|
DomainIdColumn,
|
|
14
17
|
DomainPathColumn,
|
|
15
18
|
DueDateColumn,
|
|
19
|
+
DurationColumn,
|
|
20
|
+
EmailColumn,
|
|
21
|
+
FieldListColumn,
|
|
16
22
|
FieldNameColumn,
|
|
23
|
+
FloatColumn,
|
|
24
|
+
GuidColumn,
|
|
25
|
+
HtmlColumn,
|
|
17
26
|
IntegerColumn,
|
|
18
27
|
IntegerDateColumn,
|
|
28
|
+
JsonColumn,
|
|
19
29
|
ListColumn,
|
|
30
|
+
MultiLineTextColumn,
|
|
31
|
+
NameValuePairsColumn,
|
|
20
32
|
OtherDateColumn,
|
|
33
|
+
Password2Column,
|
|
21
34
|
RadioColumn,
|
|
35
|
+
RecordsColumn,
|
|
22
36
|
ReferenceColumn,
|
|
23
37
|
ScheduleDateTimeColumn,
|
|
24
38
|
ScriptColumn,
|
|
39
|
+
SlushBucketColumn,
|
|
25
40
|
StringColumn,
|
|
26
41
|
SystemClassNameColumn,
|
|
27
42
|
TableNameColumn,
|
|
43
|
+
TemplateValueColumn,
|
|
44
|
+
TimeColumn,
|
|
28
45
|
TranslatedFieldColumn,
|
|
29
46
|
TranslatedTextColumn,
|
|
47
|
+
UrlColumn,
|
|
30
48
|
UserRolesColumn,
|
|
31
49
|
VersionColumn,
|
|
32
50
|
} from '@servicenow/sdk-core/runtime/db'
|
|
@@ -61,6 +79,25 @@ export const COLUMN_TYPE_TO_API: Record<string, string> = {
|
|
|
61
79
|
version: VersionColumn.name,
|
|
62
80
|
glide_list: ListColumn.name,
|
|
63
81
|
image: BasicImageColumn.name,
|
|
82
|
+
// New column types
|
|
83
|
+
GUID: GuidColumn.name,
|
|
84
|
+
password2: Password2Column.name,
|
|
85
|
+
json: JsonColumn.name,
|
|
86
|
+
url: UrlColumn.name,
|
|
87
|
+
email: EmailColumn.name,
|
|
88
|
+
html: HtmlColumn.name,
|
|
89
|
+
float: FloatColumn.name,
|
|
90
|
+
glide_duration: DurationColumn.name,
|
|
91
|
+
glide_time: TimeColumn.name,
|
|
92
|
+
field_list: FieldListColumn.name,
|
|
93
|
+
records: RecordsColumn.name,
|
|
94
|
+
slushbucket: SlushBucketColumn.name,
|
|
95
|
+
name_values: NameValuePairsColumn.name,
|
|
96
|
+
approval_rules: ApprovalRulesColumn.name,
|
|
97
|
+
multi_two_lines: MultiLineTextColumn.name,
|
|
98
|
+
template_value: TemplateValueColumn.name,
|
|
99
|
+
day_of_week: DayOfWeekColumn.name,
|
|
100
|
+
days_of_week: DaysOfWeekColumn.name,
|
|
64
101
|
}
|
|
65
102
|
|
|
66
103
|
export const COLUMN_API_TO_TYPE = Object.fromEntries(
|
|
@@ -87,25 +124,50 @@ export function addFieldsToColumn(
|
|
|
87
124
|
})
|
|
88
125
|
}
|
|
89
126
|
|
|
90
|
-
export function getDefaultMaxLength(columnType: string): number {
|
|
127
|
+
export function getDefaultMaxLength(columnType: string | undefined): number {
|
|
91
128
|
switch (columnType) {
|
|
92
129
|
case 'conditions':
|
|
93
130
|
case 'glide_list':
|
|
131
|
+
case 'json':
|
|
132
|
+
case 'name_values':
|
|
133
|
+
case 'multi_two_lines':
|
|
94
134
|
return 4000
|
|
135
|
+
case 'template_value':
|
|
136
|
+
return 65000
|
|
137
|
+
case 'script':
|
|
138
|
+
return 8000
|
|
139
|
+
case 'html':
|
|
140
|
+
return 65536
|
|
95
141
|
case 'decimal':
|
|
96
142
|
return 20
|
|
143
|
+
case 'float':
|
|
144
|
+
return 15
|
|
97
145
|
case 'domain_id':
|
|
98
146
|
case 'document_id':
|
|
99
147
|
case 'reference':
|
|
148
|
+
case 'GUID':
|
|
100
149
|
return 32
|
|
150
|
+
case 'string_full_utf8':
|
|
101
151
|
case 'domain_path':
|
|
102
152
|
case 'user_roles':
|
|
153
|
+
case 'password2':
|
|
154
|
+
case 'email':
|
|
103
155
|
return 255
|
|
104
|
-
case '
|
|
105
|
-
|
|
156
|
+
case 'url':
|
|
157
|
+
case 'records':
|
|
158
|
+
return 1024
|
|
106
159
|
case 'table_name':
|
|
107
160
|
case 'field_name':
|
|
108
161
|
return 80
|
|
162
|
+
case 'glide_duration':
|
|
163
|
+
return 20
|
|
164
|
+
case 'glide_time':
|
|
165
|
+
return 8
|
|
166
|
+
case 'field_list':
|
|
167
|
+
case 'approval_rules':
|
|
168
|
+
return 1024
|
|
169
|
+
case 'slushbucket':
|
|
170
|
+
return 4000
|
|
109
171
|
default:
|
|
110
172
|
/**
|
|
111
173
|
* For types mentioned below it default to 40 on instance
|