@servicenow/sdk-build-plugins 4.6.0 → 4.7.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 +3 -4
- package/dist/acl-plugin.js.map +1 -1
- package/dist/applicability-plugin.js +0 -2
- package/dist/applicability-plugin.js.map +1 -1
- package/dist/application-menu-plugin.js +0 -2
- package/dist/application-menu-plugin.js.map +1 -1
- package/dist/arrow-function-plugin.js +0 -1
- package/dist/arrow-function-plugin.js.map +1 -1
- package/dist/atf/test-plugin.js +6 -10
- package/dist/atf/test-plugin.js.map +1 -1
- package/dist/basic-syntax-plugin.js +10 -4
- package/dist/basic-syntax-plugin.js.map +1 -1
- package/dist/business-rule-plugin.js +0 -1
- package/dist/business-rule-plugin.js.map +1 -1
- package/dist/call-expression-plugin.js +0 -1
- package/dist/call-expression-plugin.js.map +1 -1
- package/dist/claims-plugin.js +0 -1
- package/dist/claims-plugin.js.map +1 -1
- package/dist/client-script-plugin.js +0 -1
- package/dist/client-script-plugin.js.map +1 -1
- package/dist/column-plugin.js +120 -49
- package/dist/column-plugin.js.map +1 -1
- package/dist/cross-scope-privilege-plugin.js +0 -1
- package/dist/cross-scope-privilege-plugin.js.map +1 -1
- package/dist/dashboard/dashboard-plugin.js +0 -2
- package/dist/dashboard/dashboard-plugin.js.map +1 -1
- package/dist/data-plugin.js +0 -1
- package/dist/data-plugin.js.map +1 -1
- package/dist/data-policy-plugin.d.ts +2 -0
- package/dist/data-policy-plugin.js +276 -0
- package/dist/data-policy-plugin.js.map +1 -0
- package/dist/email-notification-plugin.js +2 -3
- package/dist/email-notification-plugin.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-constants.d.ts +2 -0
- package/dist/flow/flow-logic/flow-logic-constants.js +6 -1
- package/dist/flow/flow-logic/flow-logic-constants.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-diagnostics.js +192 -56
- package/dist/flow/flow-logic/flow-logic-diagnostics.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-plugin-helpers.d.ts +2 -1
- package/dist/flow/flow-logic/flow-logic-plugin-helpers.js +44 -5
- package/dist/flow/flow-logic/flow-logic-plugin-helpers.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-plugin.js +279 -29
- package/dist/flow/flow-logic/flow-logic-plugin.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-shapes.d.ts +15 -0
- package/dist/flow/flow-logic/flow-logic-shapes.js +25 -1
- package/dist/flow/flow-logic/flow-logic-shapes.js.map +1 -1
- package/dist/flow/plugins/approval-rules-plugin.js +0 -1
- package/dist/flow/plugins/approval-rules-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-action-definition-plugin.js +804 -205
- package/dist/flow/plugins/flow-action-definition-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-data-pill-plugin.js +3 -5
- package/dist/flow/plugins/flow-data-pill-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-definition-plugin.js +84 -17
- package/dist/flow/plugins/flow-definition-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-diagnostics-plugin.js +65 -3
- package/dist/flow/plugins/flow-diagnostics-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-instance-plugin.js +13 -5
- package/dist/flow/plugins/flow-instance-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-trigger-instance-plugin.js +0 -1
- package/dist/flow/plugins/flow-trigger-instance-plugin.js.map +1 -1
- package/dist/flow/plugins/inline-script-plugin.js +0 -1
- package/dist/flow/plugins/inline-script-plugin.js.map +1 -1
- package/dist/flow/plugins/step-definition-plugin.js +0 -2
- package/dist/flow/plugins/step-definition-plugin.js.map +1 -1
- package/dist/flow/plugins/step-instance-plugin.js +216 -77
- package/dist/flow/plugins/step-instance-plugin.js.map +1 -1
- package/dist/flow/plugins/trigger-plugin.js +0 -2
- package/dist/flow/plugins/trigger-plugin.js.map +1 -1
- package/dist/flow/plugins/wfa-datapill-plugin.js +0 -1
- package/dist/flow/plugins/wfa-datapill-plugin.js.map +1 -1
- package/dist/flow/utils/datapill-transformer.js +9 -5
- package/dist/flow/utils/datapill-transformer.js.map +1 -1
- package/dist/flow/utils/flow-constants.d.ts +12 -0
- package/dist/flow/utils/flow-constants.js +17 -3
- package/dist/flow/utils/flow-constants.js.map +1 -1
- package/dist/flow/utils/flow-io-to-record.d.ts +1 -1
- package/dist/flow/utils/flow-io-to-record.js +21 -13
- package/dist/flow/utils/flow-io-to-record.js.map +1 -1
- package/dist/flow/utils/flow-pill-utils.d.ts +26 -0
- package/dist/flow/utils/flow-pill-utils.js +50 -0
- package/dist/flow/utils/flow-pill-utils.js.map +1 -0
- package/dist/flow/utils/flow-stage-processor.d.ts +138 -0
- package/dist/flow/utils/flow-stage-processor.js +665 -0
- package/dist/flow/utils/flow-stage-processor.js.map +1 -0
- package/dist/flow/utils/pill-string-parser.js +28 -43
- package/dist/flow/utils/pill-string-parser.js.map +1 -1
- package/dist/flow/utils/utils.d.ts +11 -6
- package/dist/flow/utils/utils.js +37 -28
- package/dist/flow/utils/utils.js.map +1 -1
- package/dist/form-plugin.js +4 -14
- package/dist/form-plugin.js.map +1 -1
- package/dist/html-import-plugin.js +0 -1
- package/dist/html-import-plugin.js.map +1 -1
- package/dist/import-sets-plugin.js +0 -2
- package/dist/import-sets-plugin.js.map +1 -1
- package/dist/inbound-email-action-plugin.js +0 -1
- package/dist/inbound-email-action-plugin.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/instance-scan-plugin.js +0 -7
- package/dist/instance-scan-plugin.js.map +1 -1
- package/dist/json-plugin.js +0 -1
- package/dist/json-plugin.js.map +1 -1
- package/dist/list-plugin.js +4 -1
- package/dist/list-plugin.js.map +1 -1
- package/dist/now-attach-plugin.js +0 -1
- package/dist/now-attach-plugin.js.map +1 -1
- package/dist/now-config-plugin.js +1 -1
- package/dist/now-config-plugin.js.map +1 -1
- package/dist/now-id-plugin.js +0 -1
- package/dist/now-id-plugin.js.map +1 -1
- package/dist/now-include-plugin.js +0 -1
- package/dist/now-include-plugin.js.map +1 -1
- package/dist/now-ref-plugin.js +0 -1
- package/dist/now-ref-plugin.js.map +1 -1
- package/dist/now-unresolved-plugin.js +0 -1
- package/dist/now-unresolved-plugin.js.map +1 -1
- package/dist/package-json-plugin.js +3 -2
- package/dist/package-json-plugin.js.map +1 -1
- package/dist/property-plugin.js +0 -2
- package/dist/property-plugin.js.map +1 -1
- package/dist/record-plugin.d.ts +2 -0
- package/dist/record-plugin.js +5 -4
- package/dist/record-plugin.js.map +1 -1
- package/dist/repack/lint/Rules.d.ts +1 -2
- package/dist/rest-api-plugin.js +6 -5
- package/dist/rest-api-plugin.js.map +1 -1
- package/dist/role-plugin.js +0 -1
- package/dist/role-plugin.js.map +1 -1
- package/dist/schedule-script/scheduled-script-plugin.js +5 -4
- package/dist/schedule-script/scheduled-script-plugin.js.map +1 -1
- package/dist/script-action-plugin.js +0 -2
- package/dist/script-action-plugin.js.map +1 -1
- package/dist/script-include-plugin.js +4 -4
- package/dist/script-include-plugin.js.map +1 -1
- package/dist/server-module-plugin/index.js +2 -3
- package/dist/server-module-plugin/index.js.map +1 -1
- package/dist/service-catalog/catalog-clientscript-plugin.js +2 -4
- package/dist/service-catalog/catalog-clientscript-plugin.js.map +1 -1
- package/dist/service-catalog/catalog-item-plugin.js +0 -2
- package/dist/service-catalog/catalog-item-plugin.js.map +1 -1
- package/dist/service-catalog/catalog-ui-policy-plugin.js +2 -4
- package/dist/service-catalog/catalog-ui-policy-plugin.js.map +1 -1
- package/dist/service-catalog/sc-record-producer-plugin.js +0 -2
- package/dist/service-catalog/sc-record-producer-plugin.js.map +1 -1
- package/dist/service-catalog/service-catalog-base.d.ts +2 -2
- package/dist/service-catalog/service-catalog-base.js +2 -2
- package/dist/service-catalog/service-catalog-base.js.map +1 -1
- package/dist/service-catalog/utils.js +1 -1
- package/dist/service-catalog/utils.js.map +1 -1
- package/dist/service-catalog/variable-set-plugin.js +0 -2
- package/dist/service-catalog/variable-set-plugin.js.map +1 -1
- package/dist/service-portal/angular-provider-plugin.js +0 -2
- package/dist/service-portal/angular-provider-plugin.js.map +1 -1
- package/dist/service-portal/dependency-plugin.js +3 -5
- package/dist/service-portal/dependency-plugin.js.map +1 -1
- package/dist/service-portal/header-footer-plugin.js +3 -5
- package/dist/service-portal/header-footer-plugin.js.map +1 -1
- package/dist/service-portal/menu-plugin.js +0 -1
- package/dist/service-portal/menu-plugin.js.map +1 -1
- package/dist/service-portal/page-plugin.js +0 -1
- package/dist/service-portal/page-plugin.js.map +1 -1
- package/dist/service-portal/page-route-map-plugin.js +0 -1
- package/dist/service-portal/page-route-map-plugin.js.map +1 -1
- package/dist/service-portal/portal-plugin.js +0 -2
- package/dist/service-portal/portal-plugin.js.map +1 -1
- package/dist/service-portal/theme-plugin.js +0 -2
- package/dist/service-portal/theme-plugin.js.map +1 -1
- package/dist/service-portal/widget-plugin.js +3 -5
- package/dist/service-portal/widget-plugin.js.map +1 -1
- package/dist/sla-plugin.js +0 -2
- package/dist/sla-plugin.js.map +1 -1
- package/dist/static-content-plugin.js +32 -3
- package/dist/static-content-plugin.js.map +1 -1
- package/dist/table-plugin.js +303 -66
- package/dist/table-plugin.js.map +1 -1
- package/dist/ui-action-plugin.js +26 -17
- package/dist/ui-action-plugin.js.map +1 -1
- package/dist/ui-page-plugin.js +159 -17
- package/dist/ui-page-plugin.js.map +1 -1
- package/dist/ui-policy-plugin.js +28 -97
- package/dist/ui-policy-plugin.js.map +1 -1
- package/dist/user-preference-plugin.js +0 -2
- package/dist/user-preference-plugin.js.map +1 -1
- package/dist/utils.d.ts +5 -9
- package/dist/utils.js +38 -11
- package/dist/utils.js.map +1 -1
- package/dist/ux-list-menu-config-plugin.js +0 -2
- package/dist/ux-list-menu-config-plugin.js.map +1 -1
- package/dist/view-plugin.js +0 -1
- package/dist/view-plugin.js.map +1 -1
- package/dist/workspace-plugin.js +0 -2
- package/dist/workspace-plugin.js.map +1 -1
- package/package.json +6 -6
- package/src/acl-plugin.ts +4 -5
- package/src/applicability-plugin.ts +0 -2
- package/src/application-menu-plugin.ts +0 -2
- package/src/arrow-function-plugin.ts +0 -1
- package/src/atf/test-plugin.ts +6 -11
- package/src/basic-syntax-plugin.ts +11 -4
- package/src/business-rule-plugin.ts +1 -2
- package/src/call-expression-plugin.ts +0 -1
- package/src/claims-plugin.ts +0 -1
- package/src/client-script-plugin.ts +1 -2
- package/src/column-plugin.ts +163 -76
- package/src/cross-scope-privilege-plugin.ts +1 -2
- package/src/dashboard/dashboard-plugin.ts +0 -2
- package/src/data-plugin.ts +0 -1
- package/src/data-policy-plugin.ts +333 -0
- package/src/email-notification-plugin.ts +8 -4
- package/src/flow/flow-logic/flow-logic-constants.ts +6 -0
- package/src/flow/flow-logic/flow-logic-diagnostics.ts +236 -58
- package/src/flow/flow-logic/flow-logic-plugin-helpers.ts +59 -6
- package/src/flow/flow-logic/flow-logic-plugin.ts +368 -38
- package/src/flow/flow-logic/flow-logic-shapes.ts +25 -0
- package/src/flow/plugins/approval-rules-plugin.ts +0 -1
- package/src/flow/plugins/flow-action-definition-plugin.ts +940 -208
- package/src/flow/plugins/flow-data-pill-plugin.ts +3 -5
- package/src/flow/plugins/flow-definition-plugin.ts +159 -26
- package/src/flow/plugins/flow-diagnostics-plugin.ts +89 -3
- package/src/flow/plugins/flow-instance-plugin.ts +26 -12
- package/src/flow/plugins/flow-trigger-instance-plugin.ts +0 -1
- package/src/flow/plugins/inline-script-plugin.ts +0 -1
- package/src/flow/plugins/step-definition-plugin.ts +0 -2
- package/src/flow/plugins/step-instance-plugin.ts +259 -65
- package/src/flow/plugins/trigger-plugin.ts +0 -2
- package/src/flow/plugins/wfa-datapill-plugin.ts +0 -1
- package/src/flow/utils/datapill-transformer.ts +13 -5
- package/src/flow/utils/flow-constants.ts +19 -1
- package/src/flow/utils/flow-io-to-record.ts +29 -19
- package/src/flow/utils/flow-pill-utils.ts +48 -0
- package/src/flow/utils/flow-stage-processor.ts +831 -0
- package/src/flow/utils/pill-string-parser.ts +29 -47
- package/src/flow/utils/utils.ts +39 -35
- package/src/form-plugin.ts +5 -15
- package/src/html-import-plugin.ts +0 -1
- package/src/import-sets-plugin.ts +0 -2
- package/src/inbound-email-action-plugin.ts +1 -2
- package/src/index.ts +7 -1
- package/src/instance-scan-plugin.ts +0 -7
- package/src/json-plugin.ts +0 -1
- package/src/list-plugin.ts +6 -2
- package/src/now-attach-plugin.ts +0 -1
- package/src/now-config-plugin.ts +1 -1
- package/src/now-id-plugin.ts +0 -1
- package/src/now-include-plugin.ts +0 -1
- package/src/now-ref-plugin.ts +0 -1
- package/src/now-unresolved-plugin.ts +0 -1
- package/src/package-json-plugin.ts +8 -3
- package/src/property-plugin.ts +0 -2
- package/src/record-plugin.ts +14 -6
- package/src/repack/lint/Rules.ts +1 -1
- package/src/rest-api-plugin.ts +7 -6
- package/src/role-plugin.ts +1 -2
- package/src/schedule-script/scheduled-script-plugin.ts +11 -5
- package/src/script-action-plugin.ts +0 -2
- package/src/script-include-plugin.ts +8 -4
- package/src/server-module-plugin/index.ts +2 -3
- package/src/service-catalog/catalog-clientscript-plugin.ts +2 -4
- package/src/service-catalog/catalog-item-plugin.ts +0 -2
- package/src/service-catalog/catalog-ui-policy-plugin.ts +2 -4
- package/src/service-catalog/sc-record-producer-plugin.ts +0 -2
- package/src/service-catalog/service-catalog-base.ts +2 -2
- package/src/service-catalog/utils.ts +1 -1
- package/src/service-catalog/variable-set-plugin.ts +0 -2
- package/src/service-portal/angular-provider-plugin.ts +0 -2
- package/src/service-portal/dependency-plugin.ts +0 -2
- package/src/service-portal/header-footer-plugin.ts +0 -2
- package/src/service-portal/menu-plugin.ts +1 -2
- package/src/service-portal/page-plugin.ts +1 -2
- package/src/service-portal/page-route-map-plugin.ts +1 -2
- package/src/service-portal/portal-plugin.ts +0 -2
- package/src/service-portal/theme-plugin.ts +0 -2
- package/src/service-portal/widget-plugin.ts +0 -2
- package/src/sla-plugin.ts +0 -2
- package/src/static-content-plugin.ts +37 -4
- package/src/table-plugin.ts +371 -92
- package/src/ui-action-plugin.ts +30 -17
- package/src/ui-page-plugin.ts +188 -20
- package/src/ui-policy-plugin.ts +33 -130
- package/src/user-preference-plugin.ts +0 -2
- package/src/utils.ts +48 -11
- package/src/ux-list-menu-config-plugin.ts +0 -2
- package/src/view-plugin.ts +0 -1
- package/src/workspace-plugin.ts +0 -2
package/src/table-plugin.ts
CHANGED
|
@@ -26,7 +26,7 @@ import { create } from 'xmlbuilder2'
|
|
|
26
26
|
import type { XMLBuilder } from 'xmlbuilder2/lib/interfaces'
|
|
27
27
|
import { addFieldsToColumn } from './column/column-helper'
|
|
28
28
|
import { getLabelForDefaultLanguage } from './column/column-to-record'
|
|
29
|
-
import {
|
|
29
|
+
import { generateDeprecatedDiagnostics, generateChoiceSetFile } from './utils'
|
|
30
30
|
import isEqual from 'lodash/isEqual'
|
|
31
31
|
|
|
32
32
|
type GlobalRecord<T extends string | number | symbol, U> = globalThis.Record<T, U>
|
|
@@ -80,6 +80,10 @@ const ColumnSchema = z
|
|
|
80
80
|
'@_use_dynamic_default': BooleanFromString.optional(),
|
|
81
81
|
'@_reference': z.string().optional(),
|
|
82
82
|
'@_virtual': BooleanFromString.optional(),
|
|
83
|
+
'@_formula': z.string().optional(),
|
|
84
|
+
'@_virtual_type': z.string().optional(),
|
|
85
|
+
'@_use_reference_qualifier': z.string().optional(),
|
|
86
|
+
'@_dynamic_ref_qual': z.string().optional(),
|
|
83
87
|
'@_calculation': z.string().optional(),
|
|
84
88
|
'@_choice_field': z.string().optional(),
|
|
85
89
|
'@_function_definition': z.string().optional(),
|
|
@@ -168,6 +172,10 @@ type ColumnDefinition = {
|
|
|
168
172
|
useDynamicDefault: boolean | undefined
|
|
169
173
|
reference: string | undefined
|
|
170
174
|
isVirtual: boolean | undefined
|
|
175
|
+
formula: string | undefined
|
|
176
|
+
virtualType: 'script' | 'formula' | undefined
|
|
177
|
+
useReferenceQualifier: 'simple' | 'dynamic' | 'advanced' | undefined
|
|
178
|
+
dynamicRefQual: string | undefined
|
|
171
179
|
calculation: string | undefined
|
|
172
180
|
choiceField: string | undefined
|
|
173
181
|
functionDefinition: string | undefined
|
|
@@ -221,6 +229,8 @@ type TableDefinition = {
|
|
|
221
229
|
actionsAccess: boolean | undefined
|
|
222
230
|
readAccess: boolean | undefined
|
|
223
231
|
isExtendable: boolean | undefined
|
|
232
|
+
createAccessControls: boolean | undefined
|
|
233
|
+
userRole: string | undefined
|
|
224
234
|
scriptableTable: boolean | undefined
|
|
225
235
|
attributes: string | undefined
|
|
226
236
|
display: string | undefined
|
|
@@ -232,6 +242,8 @@ type SysDbObjectProperties = {
|
|
|
232
242
|
label: string | undefined
|
|
233
243
|
super_class: string | undefined
|
|
234
244
|
is_extendable: boolean | undefined
|
|
245
|
+
create_access_controls: boolean | undefined
|
|
246
|
+
user_role: string | undefined
|
|
235
247
|
scriptable_table: boolean | undefined
|
|
236
248
|
client_scripts_access: boolean | undefined
|
|
237
249
|
ws_access: boolean | undefined
|
|
@@ -263,6 +275,10 @@ type SysDictionaryProperties = {
|
|
|
263
275
|
use_dynamic_default: boolean | undefined
|
|
264
276
|
reference: string | undefined
|
|
265
277
|
virtual: boolean | undefined
|
|
278
|
+
formula: string | undefined
|
|
279
|
+
virtual_type: 'script' | 'formula' | undefined
|
|
280
|
+
use_reference_qualifier: 'simple' | 'dynamic' | 'advanced' | undefined
|
|
281
|
+
dynamic_ref_qual: string | undefined
|
|
266
282
|
default: string | undefined
|
|
267
283
|
calculation: string | undefined
|
|
268
284
|
choice_field: string | undefined
|
|
@@ -384,7 +400,6 @@ const licensingAliases = {
|
|
|
384
400
|
|
|
385
401
|
export const TablePlugin = Plugin.create({
|
|
386
402
|
name: 'TablePlugin',
|
|
387
|
-
docs: [createSdkDocEntry('Table', ['sys_db_object'])],
|
|
388
403
|
files: [
|
|
389
404
|
{
|
|
390
405
|
matcher: /\.xml$/,
|
|
@@ -419,7 +434,11 @@ export const TablePlugin = Plugin.create({
|
|
|
419
434
|
await factory.createRecord({
|
|
420
435
|
source: file,
|
|
421
436
|
table,
|
|
422
|
-
properties:
|
|
437
|
+
properties: {
|
|
438
|
+
...filterUndefinedProperties(rec),
|
|
439
|
+
// Decorate generated sys_db_object
|
|
440
|
+
...(key === 'sysDbObject' || key === 'sysDictionary' ? { _bootstrap: true } : {}),
|
|
441
|
+
},
|
|
423
442
|
})
|
|
424
443
|
)
|
|
425
444
|
}
|
|
@@ -489,7 +508,7 @@ export const TablePlugin = Plugin.create({
|
|
|
489
508
|
via: 'super_class',
|
|
490
509
|
},
|
|
491
510
|
},
|
|
492
|
-
toShape(record, { descendants, config }) {
|
|
511
|
+
toShape(record, { descendants, config, compiler }) {
|
|
493
512
|
const schema: { [key: string]: CallExpressionShape } = {}
|
|
494
513
|
let displayColumn: string | undefined
|
|
495
514
|
const columns = descendants.query('sys_dictionary')
|
|
@@ -528,29 +547,41 @@ export const TablePlugin = Plugin.create({
|
|
|
528
547
|
override.transform(({ $ }) => ({
|
|
529
548
|
baseTable: $.from('base_table'),
|
|
530
549
|
default: $.from('default_value_override', 'default_value').map((flag, value) => {
|
|
531
|
-
return flag.
|
|
550
|
+
return flag.ifDefined() && flag.toBoolean()?.getValue()
|
|
551
|
+
? value.ifString()?.getValue()
|
|
552
|
+
: undefined
|
|
532
553
|
}),
|
|
533
554
|
calculation: $.from('calculation_override', 'calculation').map((flag, value) => {
|
|
534
|
-
return flag.
|
|
555
|
+
return flag.ifDefined() && flag.toBoolean()?.getValue()
|
|
556
|
+
? value.ifString()?.getValue()
|
|
557
|
+
: undefined
|
|
535
558
|
}),
|
|
536
559
|
referenceQualifier: $.from('reference_qual_override', 'reference_qual').map(
|
|
537
560
|
(flag, value) => {
|
|
538
|
-
return flag.
|
|
561
|
+
return flag.ifDefined() && flag.toBoolean()?.getValue()
|
|
562
|
+
? value.ifString()?.getValue()
|
|
563
|
+
: undefined
|
|
539
564
|
}
|
|
540
565
|
),
|
|
541
566
|
readOnlyOption: $.from('read_only_option_override', 'read_only_option').map(
|
|
542
567
|
(flag, value) => {
|
|
543
|
-
return flag.
|
|
568
|
+
return flag.ifDefined() && flag.toBoolean()?.getValue()
|
|
569
|
+
? value.ifString()?.getValue()
|
|
570
|
+
: undefined
|
|
544
571
|
}
|
|
545
572
|
),
|
|
546
573
|
dependent: $.from('dependent_override', 'dependent').map((flag, value) => {
|
|
547
|
-
return flag.
|
|
574
|
+
return flag.ifDefined() && flag.toBoolean()?.getValue()
|
|
575
|
+
? value.ifString()?.getValue()
|
|
576
|
+
: undefined
|
|
548
577
|
}),
|
|
549
578
|
mandatory: $.from('mandatory_override', 'mandatory').map((flag, value) => {
|
|
550
|
-
return flag.
|
|
579
|
+
return flag.ifDefined() && flag.toBoolean()?.getValue()
|
|
580
|
+
? value.toBoolean()?.getValue()
|
|
581
|
+
: undefined
|
|
551
582
|
}),
|
|
552
583
|
attributes: $.from('attributes_override', 'attributes').map((flag, attrs) => {
|
|
553
|
-
if (!flag.toBoolean()?.getValue() || !attrs.isString()) {
|
|
584
|
+
if (!flag.ifDefined() || !flag.toBoolean()?.getValue() || !attrs.isString()) {
|
|
554
585
|
return undefined
|
|
555
586
|
}
|
|
556
587
|
const result: { [key: string]: string | number | boolean } = {}
|
|
@@ -603,6 +634,44 @@ export const TablePlugin = Plugin.create({
|
|
|
603
634
|
// Avoid replacing call expressions with variable statements
|
|
604
635
|
const writeAsCallExpression =
|
|
605
636
|
ts.Node.isNode(originalSource) && originalSource.isKind(ts.SyntaxKind.CallExpression)
|
|
637
|
+
|
|
638
|
+
const tableName = record.get('name').asString().getValue()
|
|
639
|
+
const isBootstrapDbObject = record.get('_bootstrap').ifBoolean()?.getValue() === true
|
|
640
|
+
const nonBootstrapColumns = columns.filter(
|
|
641
|
+
(col) => col.get('_bootstrap').ifBoolean()?.getValue() !== true
|
|
642
|
+
)
|
|
643
|
+
|
|
644
|
+
// Write as augmentation if we have sys_db_object from bootstrap and columns from elsewhere
|
|
645
|
+
const isAugmentation = isBootstrapDbObject && nonBootstrapColumns.length > 0
|
|
646
|
+
if (isAugmentation) {
|
|
647
|
+
const augmentsExpression = new CallExpressionShape({
|
|
648
|
+
source: record,
|
|
649
|
+
callee: 'Table',
|
|
650
|
+
exportName: tableName,
|
|
651
|
+
args: [
|
|
652
|
+
record.transform(({ $ }) => ({
|
|
653
|
+
augments: $.val(tableName),
|
|
654
|
+
schema: $.val(schema),
|
|
655
|
+
})),
|
|
656
|
+
],
|
|
657
|
+
})
|
|
658
|
+
registerBootstrappedTable(augmentsExpression, schema, compiler)
|
|
659
|
+
return {
|
|
660
|
+
success: true,
|
|
661
|
+
value: writeAsCallExpression
|
|
662
|
+
? augmentsExpression
|
|
663
|
+
: new VariableStatementShape({
|
|
664
|
+
source: record,
|
|
665
|
+
isExported: true,
|
|
666
|
+
variableName: new IdentifierShape({
|
|
667
|
+
source: record,
|
|
668
|
+
name: tableName,
|
|
669
|
+
}),
|
|
670
|
+
initializer: augmentsExpression,
|
|
671
|
+
}),
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
606
675
|
const callExpression = new CallExpressionShape({
|
|
607
676
|
source: record,
|
|
608
677
|
callee: 'Table',
|
|
@@ -693,18 +762,24 @@ export const TablePlugin = Plugin.create({
|
|
|
693
762
|
),
|
|
694
763
|
callerAccess: $.from('caller_access')
|
|
695
764
|
.map((callerAccess) => {
|
|
765
|
+
// An empty <caller_access/> element arrives as '', not 0 — guard before
|
|
766
|
+
// '' and 0 both mean "none" on the platform — omit from generated Fluent.
|
|
767
|
+
if (callerAccess.isString() && callerAccess.getValue() === '') {
|
|
768
|
+
return ''
|
|
769
|
+
}
|
|
696
770
|
if (callerAccess.isNumber()) {
|
|
697
|
-
|
|
771
|
+
const value = callerAccess.getValue()
|
|
772
|
+
return value === 0 ? '' : callerAccessLevels[value]
|
|
698
773
|
}
|
|
699
774
|
if (callerAccess.isString()) {
|
|
700
|
-
const
|
|
701
|
-
if (!isNaN(
|
|
702
|
-
return callerAccessLevels[
|
|
775
|
+
const parsed = Number(callerAccess.getValue())
|
|
776
|
+
if (!isNaN(parsed)) {
|
|
777
|
+
return parsed === 0 ? '' : callerAccessLevels[parsed]
|
|
703
778
|
}
|
|
704
779
|
}
|
|
705
|
-
return '
|
|
780
|
+
return ''
|
|
706
781
|
})
|
|
707
|
-
.def('
|
|
782
|
+
.def(''),
|
|
708
783
|
display: displayColumn ? $.val(displayColumn) : undefined,
|
|
709
784
|
extends: $.from('super_class').def(''),
|
|
710
785
|
extensible: $.from('is_extendable').toBoolean().def(false),
|
|
@@ -725,7 +800,7 @@ export const TablePlugin = Plugin.create({
|
|
|
725
800
|
).def([]),
|
|
726
801
|
label: $.map(
|
|
727
802
|
(label) =>
|
|
728
|
-
label.ifString() ??
|
|
803
|
+
label.ifString()?.ifNotEmpty() ??
|
|
729
804
|
(tableDocumentation.length &&
|
|
730
805
|
!isDefaultDocumentation('', tableDocumentation, config.defaultLanguage)
|
|
731
806
|
? tableDocumentation.map((doc) =>
|
|
@@ -782,12 +857,24 @@ export const TablePlugin = Plugin.create({
|
|
|
782
857
|
name: $,
|
|
783
858
|
readOnly: $.val(collectionRecord?.get('read_only')).toBoolean().def(false),
|
|
784
859
|
schema: $.val(schema),
|
|
860
|
+
// create_access_controls and user_role only ever arrive here from the
|
|
861
|
+
// sys_db_object record. The platform's bootstrap XML pipeline does not
|
|
862
|
+
// touch either field (no references in /glide/db/bootstrap/xml/ or
|
|
863
|
+
// TableDescriptorProvider.createTableLevelMetaData), and the SDK's own
|
|
864
|
+
// bootstrap output is always paired with sys_db_object_<id>.xml that
|
|
865
|
+
// carries the record values. So the bootstrap-only string path through
|
|
866
|
+
// tableDefToRecordProperties is unreachable for these two fields.
|
|
867
|
+
createAccessControls: $.from('create_access_controls').toBoolean().def(false),
|
|
868
|
+
userRole: $.from('user_role')
|
|
869
|
+
.map((v) => v.ifRecordId()?.getPrimaryKey())
|
|
870
|
+
.def(''),
|
|
785
871
|
scriptableTable: $.from('scriptable_table').toBoolean().def(false),
|
|
786
872
|
textIndex: $.val(collectionRecord?.get('text_index')).toBoolean().def(false),
|
|
787
873
|
}))
|
|
788
874
|
.withAliasedKeys(tableAliases),
|
|
789
875
|
],
|
|
790
876
|
})
|
|
877
|
+
registerBootstrappedTable(callExpression, schema, compiler)
|
|
791
878
|
return {
|
|
792
879
|
success: true,
|
|
793
880
|
value: writeAsCallExpression
|
|
@@ -804,12 +891,13 @@ export const TablePlugin = Plugin.create({
|
|
|
804
891
|
}
|
|
805
892
|
},
|
|
806
893
|
async toFile(record, { descendants, config, transform }) {
|
|
807
|
-
if (
|
|
808
|
-
// Defer to record plugin
|
|
894
|
+
if (record.isDeleted()) {
|
|
809
895
|
return { success: false }
|
|
810
896
|
}
|
|
811
897
|
|
|
812
|
-
const
|
|
898
|
+
const augmentsValue = record.get('augments').ifString()?.getValue()
|
|
899
|
+
const isAugmentation = augmentsValue !== undefined
|
|
900
|
+
const tableName = augmentsValue ?? record.get('name').asString().getValue()
|
|
813
901
|
const columns = descendants.query('sys_dictionary')
|
|
814
902
|
const choices = descendants.query('sys_choice')
|
|
815
903
|
const indexes = descendants.query('sys_index')
|
|
@@ -817,6 +905,71 @@ export const TablePlugin = Plugin.create({
|
|
|
817
905
|
const licensing = descendants.query('ua_table_licensing_config')
|
|
818
906
|
const autoNumber = descendants.query('sys_number')
|
|
819
907
|
const overrides = descendants.query('sys_dictionary_override')
|
|
908
|
+
|
|
909
|
+
const [
|
|
910
|
+
documentationFiles,
|
|
911
|
+
licensingFiles,
|
|
912
|
+
autoNumberFiles,
|
|
913
|
+
overrideFiles,
|
|
914
|
+
sysDictionaryFiles,
|
|
915
|
+
sysDbObjectFiles,
|
|
916
|
+
] = await Promise.all([
|
|
917
|
+
generateRecordXml(
|
|
918
|
+
documentation.filter(
|
|
919
|
+
(doc) =>
|
|
920
|
+
!isDefaultDocumentation(
|
|
921
|
+
doc.get('element')?.toString().getValue(),
|
|
922
|
+
[doc],
|
|
923
|
+
config.defaultLanguage
|
|
924
|
+
)
|
|
925
|
+
),
|
|
926
|
+
config,
|
|
927
|
+
transform
|
|
928
|
+
),
|
|
929
|
+
generateRecordXml(
|
|
930
|
+
licensing.filter((l) => !isDefaultLicenseConfig(tableName, l)),
|
|
931
|
+
config,
|
|
932
|
+
transform
|
|
933
|
+
),
|
|
934
|
+
generateRecordXml(autoNumber, config, transform),
|
|
935
|
+
generateRecordXml(overrides, config, transform),
|
|
936
|
+
generateRecordXml(columns, config, transform, ['_bootstrap']),
|
|
937
|
+
isAugmentation
|
|
938
|
+
? Promise.resolve([])
|
|
939
|
+
: generateRecordXml([record], config, transform, ['augments', '_bootstrap']),
|
|
940
|
+
])
|
|
941
|
+
|
|
942
|
+
if (config.type === 'configuration') {
|
|
943
|
+
// No bootstrap XML for configuration projects, just write independent record XML
|
|
944
|
+
const choiceSets = descendants.query('sys_choice_set')
|
|
945
|
+
const [choiceSetFiles, indexFiles] = await Promise.all([
|
|
946
|
+
Promise.all(
|
|
947
|
+
choiceSets.map((cs) => {
|
|
948
|
+
const csChoices = choices.filter(
|
|
949
|
+
(c) =>
|
|
950
|
+
c.get('name').toString().getValue() === cs.get('name').toString().getValue() &&
|
|
951
|
+
c.get('element').toString().getValue() ===
|
|
952
|
+
cs.get('element').toString().getValue()
|
|
953
|
+
)
|
|
954
|
+
return generateChoiceSetFile(cs, csChoices, config, transform)
|
|
955
|
+
})
|
|
956
|
+
),
|
|
957
|
+
generateRecordXml(indexes, config, transform),
|
|
958
|
+
])
|
|
959
|
+
return {
|
|
960
|
+
success: true,
|
|
961
|
+
value: [
|
|
962
|
+
...sysDictionaryFiles,
|
|
963
|
+
...choiceSetFiles,
|
|
964
|
+
...indexFiles,
|
|
965
|
+
...sysDbObjectFiles,
|
|
966
|
+
...documentationFiles,
|
|
967
|
+
...licensingFiles,
|
|
968
|
+
...autoNumberFiles,
|
|
969
|
+
...overrideFiles,
|
|
970
|
+
],
|
|
971
|
+
}
|
|
972
|
+
}
|
|
820
973
|
let displayColumn: string | undefined
|
|
821
974
|
let collectionRecord: Record | undefined
|
|
822
975
|
const elements: XMLBuilder[] = []
|
|
@@ -859,7 +1012,10 @@ export const TablePlugin = Plugin.create({
|
|
|
859
1012
|
['read_only_option', column.get('read_only_option').ifString()?.getValue()],
|
|
860
1013
|
['reference_cascade_rule', column.get('reference_cascade_rule').ifString()?.getValue()],
|
|
861
1014
|
['calculation', column.get('calculation').ifString()?.getValue()],
|
|
862
|
-
|
|
1015
|
+
// Bootstrap convention: emit `choice="0"` for the platform default ("none").
|
|
1016
|
+
// The component (install) path uses an empty `<choice/>` element instead, but
|
|
1017
|
+
// bootstrap files conventionally include the literal "0" attribute.
|
|
1018
|
+
['choice', (column.get('choice').ifNumber()?.getValue() ?? 0).toString()],
|
|
863
1019
|
['choice_table', column.get('choice_table').ifString()?.getValue()],
|
|
864
1020
|
['choice_field', column.get('choice_field').ifString()?.getValue()],
|
|
865
1021
|
['display', displayValue?.toString()],
|
|
@@ -890,6 +1046,23 @@ export const TablePlugin = Plugin.create({
|
|
|
890
1046
|
['hint', column.get('hint').ifString()?.getValue()],
|
|
891
1047
|
['help', column.get('help').ifString()?.getValue()],
|
|
892
1048
|
['virtual', column.get('virtual').ifBoolean()?.getValue().toString()],
|
|
1049
|
+
['formula', column.get('formula').ifString()?.getValue() || undefined],
|
|
1050
|
+
[
|
|
1051
|
+
'virtual_type',
|
|
1052
|
+
column.get('virtual_type').ifString()?.getValue() === 'script'
|
|
1053
|
+
? undefined
|
|
1054
|
+
: column.get('virtual_type').ifString()?.getValue(),
|
|
1055
|
+
],
|
|
1056
|
+
[
|
|
1057
|
+
'use_reference_qualifier',
|
|
1058
|
+
column.get('use_reference_qualifier').ifString()?.getValue() === 'simple'
|
|
1059
|
+
? undefined
|
|
1060
|
+
: column.get('use_reference_qualifier').ifString()?.getValue(),
|
|
1061
|
+
],
|
|
1062
|
+
[
|
|
1063
|
+
'dynamic_ref_qual',
|
|
1064
|
+
column.get('dynamic_ref_qual').ifDefined()?.toString().getValue() || undefined,
|
|
1065
|
+
],
|
|
893
1066
|
['widget', column.get('widget').ifString()?.getValue()],
|
|
894
1067
|
['reference_qual', column.get('reference_qual').ifString()?.getValue()],
|
|
895
1068
|
['reference_qual_condition', column.get('reference_qual_condition').ifString()?.getValue()],
|
|
@@ -958,7 +1131,9 @@ export const TablePlugin = Plugin.create({
|
|
|
958
1131
|
['audit', collectionRecord?.get('audit').ifBoolean()?.getValue().toString()],
|
|
959
1132
|
['display', displayColumn],
|
|
960
1133
|
['access', record.get('access').ifString()?.getValue()],
|
|
961
|
-
|
|
1134
|
+
// Bootstrap convention: emit `caller_access="0"` for the platform default ("none").
|
|
1135
|
+
// The component (install) path uses an empty `<caller_access/>` element instead.
|
|
1136
|
+
['caller_access', (record.get('caller_access').ifNumber()?.getValue() ?? 0).toString()],
|
|
962
1137
|
['ws_access', record.get('ws_access').ifBoolean()?.getValue().toString()],
|
|
963
1138
|
['read_access', record.get('read_access').ifBoolean()?.getValue().toString()],
|
|
964
1139
|
['alter_access', record.get('alter_access').ifBoolean()?.getValue().toString()],
|
|
@@ -967,6 +1142,8 @@ export const TablePlugin = Plugin.create({
|
|
|
967
1142
|
['delete_access', record.get('delete_access').ifBoolean()?.getValue().toString()],
|
|
968
1143
|
['actions_access', record.get('actions_access').ifBoolean()?.getValue().toString()],
|
|
969
1144
|
['client_scripts_access', record.get('client_scripts_access').ifBoolean()?.getValue().toString()],
|
|
1145
|
+
// create_access_controls and user_role are omitted: the platform's bootstrap
|
|
1146
|
+
// pipeline doesn't read them. They're carried by the paired sys_db_object_<id>.xml.
|
|
970
1147
|
['scriptable_table', record.get('scriptable_table').ifBoolean()?.getValue().toString()],
|
|
971
1148
|
['attributes', collectionRecord?.get('attributes').ifString()?.getValue()],
|
|
972
1149
|
]
|
|
@@ -982,28 +1159,6 @@ export const TablePlugin = Plugin.create({
|
|
|
982
1159
|
]
|
|
983
1160
|
).end({ prettyPrint: true })
|
|
984
1161
|
|
|
985
|
-
const documentationFiles = await generateRecordXml(
|
|
986
|
-
documentation.filter(
|
|
987
|
-
(doc) =>
|
|
988
|
-
!isDefaultDocumentation(
|
|
989
|
-
doc.get('element')?.toString().getValue(),
|
|
990
|
-
[doc],
|
|
991
|
-
config.defaultLanguage
|
|
992
|
-
)
|
|
993
|
-
),
|
|
994
|
-
config,
|
|
995
|
-
transform
|
|
996
|
-
)
|
|
997
|
-
|
|
998
|
-
const licensingFiles = await generateRecordXml(
|
|
999
|
-
licensing.filter((licensing) => !isDefaultLicenseConfig(tableName, licensing)),
|
|
1000
|
-
config,
|
|
1001
|
-
transform
|
|
1002
|
-
)
|
|
1003
|
-
|
|
1004
|
-
const autoNumberFiles = await generateRecordXml(autoNumber, config, transform)
|
|
1005
|
-
const overrideFiles = await generateRecordXml(overrides, config, transform)
|
|
1006
|
-
|
|
1007
1162
|
return {
|
|
1008
1163
|
success: true,
|
|
1009
1164
|
value: [
|
|
@@ -1017,6 +1172,8 @@ export const TablePlugin = Plugin.create({
|
|
|
1017
1172
|
...licensingFiles,
|
|
1018
1173
|
...autoNumberFiles,
|
|
1019
1174
|
...overrideFiles,
|
|
1175
|
+
...sysDictionaryFiles,
|
|
1176
|
+
...sysDbObjectFiles,
|
|
1020
1177
|
],
|
|
1021
1178
|
}
|
|
1022
1179
|
},
|
|
@@ -1068,7 +1225,9 @@ export const TablePlugin = Plugin.create({
|
|
|
1068
1225
|
const table = callExpression.getArgument(0).asObject().withAliasedKeys(tableAliases)
|
|
1069
1226
|
generateDeprecatedDiagnostics(table, diagnostics)
|
|
1070
1227
|
const relatedRecords: Record[] = []
|
|
1071
|
-
const
|
|
1228
|
+
const augments = table.get('augments').ifString()
|
|
1229
|
+
const isAugmentation = augments !== undefined
|
|
1230
|
+
const tableName = isAugmentation ? augments! : table.get('name').asString()
|
|
1072
1231
|
if (!tableName.getValue().match(tableNameRegex)) {
|
|
1073
1232
|
diagnostics.error(
|
|
1074
1233
|
table.get('name'),
|
|
@@ -1078,16 +1237,28 @@ export const TablePlugin = Plugin.create({
|
|
|
1078
1237
|
|
|
1079
1238
|
let ignoreColumnNameCheck = false
|
|
1080
1239
|
const scopeName = config.scope
|
|
1081
|
-
const
|
|
1082
|
-
const
|
|
1083
|
-
const tableNameMatch = tableName.getValue().match(
|
|
1084
|
-
if (
|
|
1240
|
+
const scopePrefix = scopeName === 'global' ? 'u_' : `${scopeName}_`
|
|
1241
|
+
const prefixRegex = new RegExp(`^${scopePrefix}`)
|
|
1242
|
+
const tableNameMatch = tableName.getValue().match(prefixRegex)
|
|
1243
|
+
if (isAugmentation) {
|
|
1244
|
+
if (tableNameMatch && scopeName !== 'global') {
|
|
1245
|
+
const nameNode = tableName.getOriginalNode()
|
|
1246
|
+
if (!nameNode?.getParentIfKind(ts.SyntaxKind.AsExpression)) {
|
|
1247
|
+
diagnostics.error(
|
|
1248
|
+
table.get('augments'),
|
|
1249
|
+
`'augments' flag set on in-scope table '${tableName.getValue()}'`
|
|
1250
|
+
)
|
|
1251
|
+
} else {
|
|
1252
|
+
ignoreColumnNameCheck = true
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
} else if (!tableNameMatch && !isSNScope(scopeName) && scopeName !== 'global') {
|
|
1085
1256
|
const nameNode = tableName.getOriginalNode()
|
|
1086
1257
|
if (nameNode && !nameNode.getParentIfKind(ts.SyntaxKind.AsExpression)) {
|
|
1087
1258
|
// 'sn' and 'now' scoped apps ignore this validation
|
|
1088
1259
|
diagnostics.error(
|
|
1089
1260
|
table.get('name'),
|
|
1090
|
-
`'name' property should start with scope prefix '${
|
|
1261
|
+
`'name' property should start with scope prefix '${scopePrefix}'`
|
|
1091
1262
|
)
|
|
1092
1263
|
} else {
|
|
1093
1264
|
ignoreColumnNameCheck = true
|
|
@@ -1106,13 +1277,11 @@ export const TablePlugin = Plugin.create({
|
|
|
1106
1277
|
)
|
|
1107
1278
|
}
|
|
1108
1279
|
|
|
1109
|
-
const globalTableNameMatch = tableName.getValue().match(globalRegex)
|
|
1110
1280
|
let anyNonPrefixedGlobalColumn = false
|
|
1111
|
-
|
|
1112
|
-
if (scopeName === 'global' && !globalTableNameMatch) {
|
|
1281
|
+
if (!isAugmentation && scopeName === 'global' && !tableNameMatch) {
|
|
1113
1282
|
const schema = table.get('schema').asObject()
|
|
1114
1283
|
for (const [name, _] of schema.entries()) {
|
|
1115
|
-
if (!name.match(
|
|
1284
|
+
if (!name.match(prefixRegex)) {
|
|
1116
1285
|
anyNonPrefixedGlobalColumn = true
|
|
1117
1286
|
break
|
|
1118
1287
|
}
|
|
@@ -1124,7 +1293,7 @@ export const TablePlugin = Plugin.create({
|
|
|
1124
1293
|
`Global table 'name' property should start with custom prefix 'u_'`
|
|
1125
1294
|
)
|
|
1126
1295
|
}
|
|
1127
|
-
} else if (scopeName === 'global') {
|
|
1296
|
+
} else if (scopeName === 'global' && !isAugmentation) {
|
|
1128
1297
|
// Global table starts with custom prefix `u_`, allow any column name prefix
|
|
1129
1298
|
ignoreColumnNameCheck = true
|
|
1130
1299
|
}
|
|
@@ -1217,22 +1386,30 @@ export const TablePlugin = Plugin.create({
|
|
|
1217
1386
|
relatedRecords.push(overrideRecord)
|
|
1218
1387
|
} else {
|
|
1219
1388
|
// Handle regular column - create sys_dictionary record
|
|
1220
|
-
if (
|
|
1389
|
+
if (isAugmentation && !tableNameMatch) {
|
|
1390
|
+
if (!isSNScope(scopeName) && !name.match(prefixRegex)) {
|
|
1391
|
+
diagnostics.error(
|
|
1392
|
+
column.getOriginalNode().getParentIfKind(ts.SyntaxKind.PropertyAssignment) ??
|
|
1393
|
+
column,
|
|
1394
|
+
`Column name '${name}' must be prefixed with '${scopePrefix}' when augmenting a table`
|
|
1395
|
+
)
|
|
1396
|
+
}
|
|
1397
|
+
} else if (
|
|
1221
1398
|
!ignoreColumnNameCheck &&
|
|
1222
1399
|
!tableNameMatch &&
|
|
1223
1400
|
!isSNScope(scopeName) &&
|
|
1224
1401
|
scopeName !== 'global' &&
|
|
1225
|
-
!name.match(
|
|
1402
|
+
!name.match(prefixRegex)
|
|
1226
1403
|
) {
|
|
1227
1404
|
// 'sn' and 'now' scoped apps ignore this validation
|
|
1228
1405
|
diagnostics.error(
|
|
1229
1406
|
column.getOriginalNode().getParentIfKind(ts.SyntaxKind.PropertyAssignment) ?? column,
|
|
1230
|
-
`Column name should be prefixed with scope '${
|
|
1407
|
+
`Column name should be prefixed with scope '${scopePrefix}' if table name does not contain prefix`
|
|
1231
1408
|
)
|
|
1232
|
-
} else if (scopeName === 'global' && !
|
|
1409
|
+
} else if (scopeName === 'global' && !tableNameMatch && !name.match(prefixRegex)) {
|
|
1233
1410
|
diagnostics.error(
|
|
1234
1411
|
column.getOriginalNode().getParentIfKind(ts.SyntaxKind.PropertyAssignment) ?? column,
|
|
1235
|
-
`Column name should be prefixed with '
|
|
1412
|
+
`Column name should be prefixed with '${scopePrefix}' custom prefix if table name does not contain this prefix, such as when adding columns to an existing global table`
|
|
1236
1413
|
)
|
|
1237
1414
|
}
|
|
1238
1415
|
const display = table.get('display').ifString()?.getValue() === name
|
|
@@ -1409,29 +1586,32 @@ export const TablePlugin = Plugin.create({
|
|
|
1409
1586
|
}
|
|
1410
1587
|
|
|
1411
1588
|
// sys_dictionary (collection)
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
.
|
|
1427
|
-
.
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1589
|
+
if (!isAugmentation) {
|
|
1590
|
+
relatedRecords.push(
|
|
1591
|
+
await factory.createRecord({
|
|
1592
|
+
source: statement ?? callExpression,
|
|
1593
|
+
table: 'sys_dictionary',
|
|
1594
|
+
properties: table.transform(({ $ }) => ({
|
|
1595
|
+
name: $,
|
|
1596
|
+
element: $.val(undefined),
|
|
1597
|
+
internal_type: $.def('collection'),
|
|
1598
|
+
active: $.val(true),
|
|
1599
|
+
attributes: $.map((attributes) => {
|
|
1600
|
+
if (!attributes.isObject()) {
|
|
1601
|
+
return undefined
|
|
1602
|
+
}
|
|
1603
|
+
const attributesObj = attributes.asObject().getValue()
|
|
1604
|
+
return Object.entries(attributesObj)
|
|
1605
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
1606
|
+
.join(',')
|
|
1607
|
+
}).def(''),
|
|
1608
|
+
audit: $.def(false),
|
|
1609
|
+
read_only: $.from('readOnly').def(false),
|
|
1610
|
+
text_index: $.from('textIndex').def(false),
|
|
1611
|
+
})),
|
|
1612
|
+
})
|
|
1613
|
+
)
|
|
1614
|
+
}
|
|
1435
1615
|
|
|
1436
1616
|
const hasAction = (actionName: string, actions: Shape): boolean | undefined => {
|
|
1437
1617
|
return actions
|
|
@@ -1449,6 +1629,17 @@ export const TablePlugin = Plugin.create({
|
|
|
1449
1629
|
})
|
|
1450
1630
|
: ext.ifDefined()?.toRecordId()
|
|
1451
1631
|
|
|
1632
|
+
const userRoleField = table.get('userRole')
|
|
1633
|
+
const userRoleReference = userRoleField.isString()
|
|
1634
|
+
? userRoleField.getValue() === ''
|
|
1635
|
+
? undefined
|
|
1636
|
+
: await factory.createReference({
|
|
1637
|
+
source: userRoleField,
|
|
1638
|
+
table: 'sys_user_role',
|
|
1639
|
+
keys: { name: userRoleField },
|
|
1640
|
+
})
|
|
1641
|
+
: userRoleField.ifDefined()?.toRecordId()
|
|
1642
|
+
|
|
1452
1643
|
// sys_db_object
|
|
1453
1644
|
const tableRecord = await factory.createRecord({
|
|
1454
1645
|
source: statement ?? callExpression,
|
|
@@ -1460,11 +1651,15 @@ export const TablePlugin = Plugin.create({
|
|
|
1460
1651
|
ws_access: $.from('allowWebServiceAccess').toBoolean().def(false),
|
|
1461
1652
|
number_ref: $.val(numberRef),
|
|
1462
1653
|
access: $.from('accessibleFrom').def('public'),
|
|
1463
|
-
caller_access: $.from('callerAccess').map((callerAccess) =>
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1654
|
+
caller_access: $.from('callerAccess').map((callerAccess) => {
|
|
1655
|
+
const value = callerAccess.ifString()?.getValue()
|
|
1656
|
+
if (!value) {
|
|
1657
|
+
return undefined
|
|
1658
|
+
}
|
|
1659
|
+
const index = callerAccessLevels.indexOf(value as 'none' | 'tracking' | 'restricted')
|
|
1660
|
+
// index 0 ('none') is the platform default — emit empty <caller_access/>, matching stock.
|
|
1661
|
+
return index > 0 ? index : undefined
|
|
1662
|
+
}),
|
|
1468
1663
|
super_class: $.val(parentReference),
|
|
1469
1664
|
read_access: $.from('actions')
|
|
1470
1665
|
.map((actions) => hasAction('read', actions))
|
|
@@ -1481,8 +1676,14 @@ export const TablePlugin = Plugin.create({
|
|
|
1481
1676
|
is_extendable: $.from('extensible').toBoolean().def(false),
|
|
1482
1677
|
label: $.map((label) => getLabelForDefaultLanguage(label, config.defaultLanguage)),
|
|
1483
1678
|
live_feed_enabled: $.from('liveFeed').toBoolean().def(false),
|
|
1484
|
-
name:
|
|
1679
|
+
name: $.from('name', 'augments').map(
|
|
1680
|
+
(nameVal, augmentsVal) => augmentsVal.ifString() ?? nameVal
|
|
1681
|
+
),
|
|
1682
|
+
create_access_controls: $.from('createAccessControls').toBoolean().def(false),
|
|
1683
|
+
user_role: $.val(userRoleReference),
|
|
1485
1684
|
scriptable_table: $.from('scriptableTable').toBoolean().def(false),
|
|
1685
|
+
// Controls toFile output, not written to record XML
|
|
1686
|
+
augments: $.from('augments'),
|
|
1486
1687
|
})),
|
|
1487
1688
|
})
|
|
1488
1689
|
|
|
@@ -1569,6 +1770,18 @@ function parseTableBootstrapXml(xml: unknown): TableDefinition | null {
|
|
|
1569
1770
|
useDynamicDefault: column['@_use_dynamic_default'],
|
|
1570
1771
|
reference: column['@_reference'],
|
|
1571
1772
|
isVirtual: column['@_virtual'],
|
|
1773
|
+
formula: column['@_formula'],
|
|
1774
|
+
virtualType:
|
|
1775
|
+
column['@_virtual_type'] === 'script' || column['@_virtual_type'] === 'formula'
|
|
1776
|
+
? column['@_virtual_type']
|
|
1777
|
+
: undefined,
|
|
1778
|
+
useReferenceQualifier:
|
|
1779
|
+
column['@_use_reference_qualifier'] === 'simple' ||
|
|
1780
|
+
column['@_use_reference_qualifier'] === 'dynamic' ||
|
|
1781
|
+
column['@_use_reference_qualifier'] === 'advanced'
|
|
1782
|
+
? column['@_use_reference_qualifier']
|
|
1783
|
+
: undefined,
|
|
1784
|
+
dynamicRefQual: column['@_dynamic_ref_qual'],
|
|
1572
1785
|
calculation: column['@_calculation'],
|
|
1573
1786
|
choiceField: column['@_choice_field'],
|
|
1574
1787
|
functionDefinition: column['@_function_definition'],
|
|
@@ -1642,6 +1855,8 @@ function parseTableBootstrapXml(xml: unknown): TableDefinition | null {
|
|
|
1642
1855
|
actionsAccess: table['@_actions_access'],
|
|
1643
1856
|
readAccess: table['@_read_access'],
|
|
1644
1857
|
isExtendable: table['@_is_extendable'],
|
|
1858
|
+
createAccessControls: table['@_create_access_controls'],
|
|
1859
|
+
userRole: table['@_user_role'],
|
|
1645
1860
|
scriptableTable: table['@_scriptable_table'],
|
|
1646
1861
|
attributes: table['@_attributes'],
|
|
1647
1862
|
}
|
|
@@ -1663,6 +1878,8 @@ function tableDefToRecordProperties(
|
|
|
1663
1878
|
label: tableDef.label,
|
|
1664
1879
|
super_class: tableDef.extends,
|
|
1665
1880
|
is_extendable: tableDef.isExtendable,
|
|
1881
|
+
create_access_controls: tableDef.createAccessControls,
|
|
1882
|
+
user_role: tableDef.userRole,
|
|
1666
1883
|
scriptable_table: tableDef.scriptableTable,
|
|
1667
1884
|
client_scripts_access: tableDef.clientScriptsAccess,
|
|
1668
1885
|
ws_access: tableDef.wsAccess,
|
|
@@ -1712,6 +1929,10 @@ function tableDefToRecordProperties(
|
|
|
1712
1929
|
use_dynamic_default: column.useDynamicDefault,
|
|
1713
1930
|
reference: column.reference,
|
|
1714
1931
|
virtual: column.isVirtual,
|
|
1932
|
+
formula: column.formula,
|
|
1933
|
+
virtual_type: column.virtualType,
|
|
1934
|
+
use_reference_qualifier: column.useReferenceQualifier,
|
|
1935
|
+
dynamic_ref_qual: column.dynamicRefQual,
|
|
1715
1936
|
default: column.defaultValue,
|
|
1716
1937
|
calculation: column.calculation,
|
|
1717
1938
|
choice_field: column.choiceField,
|
|
@@ -1794,6 +2015,10 @@ function tableDefToRecordProperties(
|
|
|
1794
2015
|
use_dynamic_default: undefined,
|
|
1795
2016
|
reference: undefined,
|
|
1796
2017
|
virtual: undefined,
|
|
2018
|
+
formula: undefined,
|
|
2019
|
+
virtual_type: undefined,
|
|
2020
|
+
use_reference_qualifier: undefined,
|
|
2021
|
+
dynamic_ref_qual: undefined,
|
|
1797
2022
|
default: undefined,
|
|
1798
2023
|
calculation: undefined,
|
|
1799
2024
|
choice_field: undefined,
|
|
@@ -1852,7 +2077,7 @@ function addTableToGlobalGeneratedFile(tableArg: ObjectShape, sourceFilePath: st
|
|
|
1852
2077
|
>,
|
|
1853
2078
|
}
|
|
1854
2079
|
const generatedTableFile: ts.SourceFile | undefined = compiler.getGeneratedTableFile()
|
|
1855
|
-
const tableName = tableArg.get('name').asString().getValue()
|
|
2080
|
+
const tableName = tableArg.get('augments').ifString()?.getValue() ?? tableArg.get('name').asString().getValue()
|
|
1856
2081
|
if (!(tableName.trim().length > 0 && tableName.match(tableNameRegex))) {
|
|
1857
2082
|
return
|
|
1858
2083
|
}
|
|
@@ -1910,6 +2135,58 @@ function addTableToGlobalGeneratedFile(tableArg: ObjectShape, sourceFilePath: st
|
|
|
1910
2135
|
}
|
|
1911
2136
|
}
|
|
1912
2137
|
|
|
2138
|
+
/**
|
|
2139
|
+
* Records a bootstrap-derived Table() shape into $$GENERATED$$_bootstrapped_tables.ts so that other plugins (e.g. RecordPlugin)
|
|
2140
|
+
* can resolve Data<T> column types via TypeScript during the same transform pass — no sys_dictionary query needed.
|
|
2141
|
+
*
|
|
2142
|
+
* The `declare global` augmentation lives inside the bootstrapped file (referencing its LOCAL `typeof tableName` export) rather
|
|
2143
|
+
* than the common table file. That avoids the duplicate-import error when a pre-existing Fluent Table() of the same name was
|
|
2144
|
+
* already wired into the common file, and TypeScript still merges the two TableSchemas interface declarations so both
|
|
2145
|
+
* contribute their columns to the resolved Data<T>.
|
|
2146
|
+
*/
|
|
2147
|
+
function registerBootstrappedTable(
|
|
2148
|
+
tableCall: CallExpressionShape,
|
|
2149
|
+
schema: { [key: string]: CallExpressionShape },
|
|
2150
|
+
compiler: Compiler
|
|
2151
|
+
): void {
|
|
2152
|
+
const file = compiler.getGeneratedBootstrappedTablesFile()
|
|
2153
|
+
if (!file || Object.keys(schema).length === 0) {
|
|
2154
|
+
return
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
const tableArg = tableCall.getArgument(0).asObject()
|
|
2158
|
+
const tableName = tableArg.get('augments').ifString()?.getValue() ?? tableArg.get('name').asString().getValue()
|
|
2159
|
+
|
|
2160
|
+
const tableSchemas = file.getModule('global')?.getModule('Now')?.getModule('Internal')?.getModule('TableSchemas')
|
|
2161
|
+
const tables = file.getModule('global')?.getModule('Now')?.getModule('Internal')?.getInterface('Tables')
|
|
2162
|
+
if (!tableSchemas || !tables) {
|
|
2163
|
+
return
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
const coreImport = file.getImportDeclaration('@servicenow/sdk/core')
|
|
2167
|
+
const existingImports = new Set(coreImport?.getNamedImports().map((n) => n.getName()))
|
|
2168
|
+
for (const callee of new Set(Object.values(schema).map((s) => s.getCallee()))) {
|
|
2169
|
+
if (!existingImports.has(callee)) {
|
|
2170
|
+
coreImport?.addNamedImport(callee)
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
// Replace any existing export (re-transform of same XML), then write the shape's rendered code.
|
|
2175
|
+
file.getVariableDeclaration(tableName)?.getVariableStatement()?.remove()
|
|
2176
|
+
file.addVariableStatement({
|
|
2177
|
+
isExported: true,
|
|
2178
|
+
declarationKind: ts.VariableDeclarationKind.Const,
|
|
2179
|
+
declarations: [{ name: tableName, initializer: tableCall.getCode() }],
|
|
2180
|
+
})
|
|
2181
|
+
|
|
2182
|
+
if (!tableSchemas.getInterface(tableName)) {
|
|
2183
|
+
tableSchemas.addInterface({ name: tableName, extends: [`Helper<typeof ${tableName}>`] })
|
|
2184
|
+
}
|
|
2185
|
+
if (!tables.getProperty(tableName)) {
|
|
2186
|
+
tables.addProperty({ name: tableName, type: `Table<TableSchemas.${tableName}>` })
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
|
|
1913
2190
|
function filterUndefinedProperties<T extends object>(obj: T): T {
|
|
1914
2191
|
return Object.fromEntries(Object.entries(obj).filter(([_, value]) => value !== undefined)) as T
|
|
1915
2192
|
}
|
|
@@ -1933,7 +2210,8 @@ function createElement(name: string, attributes: [string, string][] = [], childr
|
|
|
1933
2210
|
async function generateRecordXml(
|
|
1934
2211
|
records: Record[],
|
|
1935
2212
|
config: { scope: string; scopeId: string },
|
|
1936
|
-
transform: Transform
|
|
2213
|
+
transform: Transform,
|
|
2214
|
+
excludeFields: string[] = []
|
|
1937
2215
|
): Promise<OutputFile[]> {
|
|
1938
2216
|
const files: OutputFile[] = []
|
|
1939
2217
|
for (const record of records) {
|
|
@@ -1944,6 +2222,7 @@ async function generateRecordXml(
|
|
|
1944
2222
|
record
|
|
1945
2223
|
.entries()
|
|
1946
2224
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
2225
|
+
.filter(([prop]) => excludeFields.length === 0 || !excludeFields.includes(prop))
|
|
1947
2226
|
.forEach(([prop, shape]) => builder.field(prop, shape))
|
|
1948
2227
|
|
|
1949
2228
|
files.push({
|