@servicenow/sdk-build-plugins 4.4.0 → 4.5.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 +54 -4
- package/dist/acl-plugin.js.map +1 -1
- package/dist/applicability-plugin.js +2 -0
- package/dist/applicability-plugin.js.map +1 -1
- package/dist/application-menu-plugin.js +2 -0
- package/dist/application-menu-plugin.js.map +1 -1
- package/dist/arrow-function-plugin.d.ts +6 -1
- package/dist/arrow-function-plugin.js +105 -12
- package/dist/arrow-function-plugin.js.map +1 -1
- package/dist/atf/test-plugin.js +2 -0
- package/dist/atf/test-plugin.js.map +1 -1
- package/dist/basic-syntax-plugin.js +20 -0
- package/dist/basic-syntax-plugin.js.map +1 -1
- package/dist/call-expression-plugin.js +1 -0
- package/dist/call-expression-plugin.js.map +1 -1
- package/dist/claims-plugin.js +1 -0
- package/dist/claims-plugin.js.map +1 -1
- package/dist/client-script-plugin.js +1 -0
- package/dist/client-script-plugin.js.map +1 -1
- package/dist/column-plugin.js +1 -0
- package/dist/column-plugin.js.map +1 -1
- package/dist/cross-scope-privilege-plugin.js +1 -0
- package/dist/cross-scope-privilege-plugin.js.map +1 -1
- package/dist/dashboard/dashboard-plugin.js +2 -0
- package/dist/dashboard/dashboard-plugin.js.map +1 -1
- package/dist/data-plugin.js +1 -0
- package/dist/data-plugin.js.map +1 -1
- package/dist/email-notification-plugin.js +9 -13
- package/dist/email-notification-plugin.js.map +1 -1
- package/dist/flow/constants/flow-plugin-constants.d.ts +1 -1
- package/dist/flow/constants/flow-plugin-constants.js +1 -1
- package/dist/flow/constants/flow-plugin-constants.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-plugin-helpers.d.ts +82 -2
- package/dist/flow/flow-logic/flow-logic-plugin-helpers.js +48 -40
- package/dist/flow/flow-logic/flow-logic-plugin-helpers.js.map +1 -1
- package/dist/flow/flow-logic/flow-logic-plugin.js +1 -0
- package/dist/flow/flow-logic/flow-logic-plugin.js.map +1 -1
- package/dist/flow/plugins/approval-rules-plugin.js +1 -0
- package/dist/flow/plugins/approval-rules-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-action-definition-plugin.js +4 -2
- package/dist/flow/plugins/flow-action-definition-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-data-pill-plugin.js +1 -0
- package/dist/flow/plugins/flow-data-pill-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-definition-plugin.js +8 -3
- package/dist/flow/plugins/flow-definition-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-diagnostics-plugin.js +1 -0
- package/dist/flow/plugins/flow-diagnostics-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-instance-plugin.js +68 -12
- package/dist/flow/plugins/flow-instance-plugin.js.map +1 -1
- package/dist/flow/plugins/flow-trigger-instance-plugin.js +1 -0
- package/dist/flow/plugins/flow-trigger-instance-plugin.js.map +1 -1
- package/dist/flow/plugins/inline-script-plugin.js +1 -0
- package/dist/flow/plugins/inline-script-plugin.js.map +1 -1
- package/dist/flow/plugins/step-definition-plugin.js +3 -2
- package/dist/flow/plugins/step-definition-plugin.js.map +1 -1
- package/dist/flow/plugins/step-instance-plugin.js +1 -0
- package/dist/flow/plugins/step-instance-plugin.js.map +1 -1
- package/dist/flow/plugins/trigger-plugin.js +2 -0
- package/dist/flow/plugins/trigger-plugin.js.map +1 -1
- package/dist/flow/plugins/wfa-datapill-plugin.js +1 -0
- package/dist/flow/plugins/wfa-datapill-plugin.js.map +1 -1
- package/dist/flow/post-install.d.ts +2 -0
- package/dist/flow/post-install.js +58 -0
- package/dist/flow/post-install.js.map +1 -0
- package/dist/flow/utils/complex-objects.js +4 -2
- package/dist/flow/utils/complex-objects.js.map +1 -1
- package/dist/flow/utils/flow-constants.d.ts +24 -0
- package/dist/flow/utils/flow-constants.js +29 -2
- package/dist/flow/utils/flow-constants.js.map +1 -1
- package/dist/flow/utils/flow-to-xml.d.ts +3 -2
- package/dist/flow/utils/flow-to-xml.js +3 -4
- package/dist/flow/utils/flow-to-xml.js.map +1 -1
- package/dist/flow/utils/label-cache-processor.d.ts +5 -0
- package/dist/flow/utils/label-cache-processor.js +14 -2
- package/dist/flow/utils/label-cache-processor.js.map +1 -1
- package/dist/flow/utils/service-catalog.js +5 -1
- package/dist/flow/utils/service-catalog.js.map +1 -1
- package/dist/form-plugin.d.ts +2 -0
- package/dist/form-plugin.js +1134 -0
- package/dist/form-plugin.js.map +1 -0
- package/dist/html-import-plugin.js +1 -0
- package/dist/html-import-plugin.js.map +1 -1
- package/dist/import-sets-plugin.js +2 -0
- package/dist/import-sets-plugin.js.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/instance-scan-plugin.d.ts +2 -0
- package/dist/instance-scan-plugin.js +298 -0
- package/dist/instance-scan-plugin.js.map +1 -0
- package/dist/json-plugin.js +1 -0
- package/dist/json-plugin.js.map +1 -1
- package/dist/list-plugin.js +1 -0
- package/dist/list-plugin.js.map +1 -1
- package/dist/now-attach-plugin.js +1 -0
- package/dist/now-attach-plugin.js.map +1 -1
- package/dist/now-config-plugin.js +659 -51
- package/dist/now-config-plugin.js.map +1 -1
- package/dist/now-id-plugin.js +1 -0
- package/dist/now-id-plugin.js.map +1 -1
- package/dist/now-include-plugin.js +1 -0
- package/dist/now-include-plugin.js.map +1 -1
- package/dist/now-ref-plugin.js +1 -0
- package/dist/now-ref-plugin.js.map +1 -1
- package/dist/now-unresolved-plugin.js +1 -0
- package/dist/now-unresolved-plugin.js.map +1 -1
- package/dist/package-json-plugin.js +1 -0
- package/dist/package-json-plugin.js.map +1 -1
- package/dist/property-plugin.js +3 -1
- package/dist/property-plugin.js.map +1 -1
- package/dist/record-plugin.d.ts +30 -0
- package/dist/record-plugin.js +37 -1
- package/dist/record-plugin.js.map +1 -1
- package/dist/repack/lint/Rules.d.ts +11 -2
- package/dist/repack/lint/Rules.js +160 -16
- package/dist/repack/lint/Rules.js.map +1 -1
- package/dist/repack/lint/index.d.ts +10 -5
- package/dist/repack/lint/index.js +76 -50
- package/dist/repack/lint/index.js.map +1 -1
- package/dist/rest-api-plugin.js +14 -0
- 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/schedule-script/index.d.ts +1 -0
- package/dist/schedule-script/index.js +18 -0
- package/dist/schedule-script/index.js.map +1 -0
- package/dist/schedule-script/scheduled-script-plugin.d.ts +2 -0
- package/dist/schedule-script/scheduled-script-plugin.js +551 -0
- package/dist/schedule-script/scheduled-script-plugin.js.map +1 -0
- package/dist/schedule-script/timeZoneConverter.d.ts +61 -0
- package/dist/schedule-script/timeZoneConverter.js +170 -0
- package/dist/schedule-script/timeZoneConverter.js.map +1 -0
- package/dist/script-action-plugin.js +2 -0
- package/dist/script-action-plugin.js.map +1 -1
- package/dist/script-include-plugin.js +2 -0
- package/dist/script-include-plugin.js.map +1 -1
- package/dist/server-module-plugin/index.js +13 -2
- package/dist/server-module-plugin/index.js.map +1 -1
- package/dist/service-catalog/catalog-clientscript-plugin.js +2 -0
- package/dist/service-catalog/catalog-clientscript-plugin.js.map +1 -1
- package/dist/service-catalog/catalog-item-plugin.js +2 -0
- package/dist/service-catalog/catalog-item-plugin.js.map +1 -1
- package/dist/service-catalog/catalog-ui-policy-plugin.js +2 -0
- package/dist/service-catalog/catalog-ui-policy-plugin.js.map +1 -1
- package/dist/service-catalog/sc-record-producer-plugin.js +2 -0
- package/dist/service-catalog/sc-record-producer-plugin.js.map +1 -1
- package/dist/service-catalog/service-catalog-diagnostics.d.ts +6 -0
- package/dist/service-catalog/service-catalog-diagnostics.js +20 -0
- package/dist/service-catalog/service-catalog-diagnostics.js.map +1 -1
- package/dist/service-catalog/shape-to-record.js +7 -2
- package/dist/service-catalog/shape-to-record.js.map +1 -1
- package/dist/service-catalog/variable-set-plugin.js +2 -0
- package/dist/service-catalog/variable-set-plugin.js.map +1 -1
- package/dist/service-portal/angular-provider-plugin.js +2 -0
- package/dist/service-portal/angular-provider-plugin.js.map +1 -1
- package/dist/service-portal/dependency-plugin.js +5 -31
- package/dist/service-portal/dependency-plugin.js.map +1 -1
- package/dist/service-portal/menu-plugin.d.ts +2 -0
- package/dist/service-portal/menu-plugin.js +353 -0
- package/dist/service-portal/menu-plugin.js.map +1 -0
- package/dist/service-portal/page-plugin.d.ts +2 -0
- package/dist/service-portal/page-plugin.js +702 -0
- package/dist/service-portal/page-plugin.js.map +1 -0
- package/dist/service-portal/portal-plugin.d.ts +2 -0
- package/dist/service-portal/portal-plugin.js +296 -0
- package/dist/service-portal/portal-plugin.js.map +1 -0
- package/dist/service-portal/theme-plugin.d.ts +2 -0
- package/dist/service-portal/theme-plugin.js +112 -0
- package/dist/service-portal/theme-plugin.js.map +1 -0
- package/dist/service-portal/utils.d.ts +8 -0
- package/dist/service-portal/utils.js +50 -0
- package/dist/service-portal/utils.js.map +1 -0
- package/dist/service-portal/widget-plugin.js +45 -8
- package/dist/service-portal/widget-plugin.js.map +1 -1
- package/dist/sla-plugin.js +2 -0
- package/dist/sla-plugin.js.map +1 -1
- package/dist/static-content-plugin.js +1 -0
- package/dist/static-content-plugin.js.map +1 -1
- package/dist/table-plugin.js +1 -0
- package/dist/table-plugin.js.map +1 -1
- package/dist/ui-action-plugin.js +2 -0
- package/dist/ui-action-plugin.js.map +1 -1
- package/dist/ui-page-plugin.js +33 -8
- package/dist/ui-page-plugin.js.map +1 -1
- package/dist/ui-policy-plugin.js +1 -0
- package/dist/ui-policy-plugin.js.map +1 -1
- package/dist/user-preference-plugin.js +2 -0
- package/dist/user-preference-plugin.js.map +1 -1
- package/dist/utils.d.ts +20 -2
- package/dist/utils.js +34 -3
- package/dist/utils.js.map +1 -1
- package/dist/ux-list-menu-config-plugin.js +2 -0
- package/dist/ux-list-menu-config-plugin.js.map +1 -1
- package/dist/view-plugin.js +1 -0
- package/dist/view-plugin.js.map +1 -1
- package/dist/workspace-plugin.js +2 -0
- package/dist/workspace-plugin.js.map +1 -1
- package/package.json +10 -11
- package/src/_types/eslint-community-eslint-utils.d.ts +15 -0
- package/src/acl-plugin.ts +97 -8
- package/src/applicability-plugin.ts +2 -0
- package/src/application-menu-plugin.ts +2 -0
- package/src/arrow-function-plugin.ts +128 -13
- package/src/atf/test-plugin.ts +2 -0
- package/src/basic-syntax-plugin.ts +21 -0
- package/src/call-expression-plugin.ts +1 -0
- package/src/claims-plugin.ts +1 -0
- package/src/client-script-plugin.ts +2 -1
- package/src/column-plugin.ts +1 -0
- package/src/cross-scope-privilege-plugin.ts +2 -1
- package/src/dashboard/dashboard-plugin.ts +2 -0
- package/src/data-plugin.ts +1 -0
- package/src/email-notification-plugin.ts +3 -23
- package/src/flow/constants/flow-plugin-constants.ts +1 -1
- package/src/flow/flow-logic/flow-logic-plugin-helpers.ts +47 -45
- package/src/flow/flow-logic/flow-logic-plugin.ts +1 -0
- package/src/flow/plugins/approval-rules-plugin.ts +1 -0
- package/src/flow/plugins/flow-action-definition-plugin.ts +4 -2
- package/src/flow/plugins/flow-data-pill-plugin.ts +1 -0
- package/src/flow/plugins/flow-definition-plugin.ts +10 -4
- package/src/flow/plugins/flow-diagnostics-plugin.ts +1 -0
- package/src/flow/plugins/flow-instance-plugin.ts +103 -14
- package/src/flow/plugins/flow-trigger-instance-plugin.ts +1 -0
- package/src/flow/plugins/inline-script-plugin.ts +1 -0
- package/src/flow/plugins/step-definition-plugin.ts +3 -2
- package/src/flow/plugins/step-instance-plugin.ts +1 -0
- package/src/flow/plugins/trigger-plugin.ts +2 -0
- package/src/flow/plugins/wfa-datapill-plugin.ts +1 -0
- package/src/flow/post-install.ts +92 -0
- package/src/flow/utils/complex-objects.ts +10 -2
- package/src/flow/utils/flow-constants.ts +30 -1
- package/src/flow/utils/flow-to-xml.ts +4 -4
- package/src/flow/utils/label-cache-processor.ts +14 -2
- package/src/flow/utils/service-catalog.ts +5 -2
- package/src/form-plugin.ts +1411 -0
- package/src/html-import-plugin.ts +1 -0
- package/src/import-sets-plugin.ts +2 -0
- package/src/index.ts +9 -0
- package/src/instance-scan-plugin.ts +318 -0
- package/src/json-plugin.ts +1 -0
- package/src/list-plugin.ts +2 -1
- package/src/now-attach-plugin.ts +1 -0
- package/src/now-config-plugin.ts +833 -53
- package/src/now-id-plugin.ts +1 -0
- package/src/now-include-plugin.ts +1 -0
- package/src/now-ref-plugin.ts +1 -0
- package/src/now-unresolved-plugin.ts +1 -0
- package/src/package-json-plugin.ts +1 -0
- package/src/property-plugin.ts +3 -1
- package/src/record-plugin.ts +42 -2
- package/src/repack/lint/Rules.ts +171 -22
- package/src/repack/lint/index.ts +80 -56
- package/src/rest-api-plugin.ts +21 -1
- package/src/role-plugin.ts +2 -1
- package/src/schedule-script/index.ts +1 -0
- package/src/schedule-script/scheduled-script-plugin.ts +679 -0
- package/src/schedule-script/timeZoneConverter.ts +188 -0
- package/src/script-action-plugin.ts +2 -0
- package/src/script-include-plugin.ts +2 -0
- package/src/server-module-plugin/index.ts +14 -2
- package/src/service-catalog/catalog-clientscript-plugin.ts +2 -0
- package/src/service-catalog/catalog-item-plugin.ts +2 -0
- package/src/service-catalog/catalog-ui-policy-plugin.ts +2 -0
- package/src/service-catalog/sc-record-producer-plugin.ts +2 -0
- package/src/service-catalog/service-catalog-diagnostics.ts +30 -0
- package/src/service-catalog/shape-to-record.ts +8 -2
- package/src/service-catalog/variable-set-plugin.ts +2 -0
- package/src/service-portal/angular-provider-plugin.ts +2 -0
- package/src/service-portal/dependency-plugin.ts +6 -53
- package/src/service-portal/menu-plugin.ts +435 -0
- package/src/service-portal/page-plugin.ts +830 -0
- package/src/service-portal/portal-plugin.ts +319 -0
- package/src/service-portal/theme-plugin.ts +135 -0
- package/src/service-portal/utils.ts +69 -0
- package/src/service-portal/widget-plugin.ts +79 -9
- package/src/sla-plugin.ts +2 -0
- package/src/static-content-plugin.ts +1 -0
- package/src/table-plugin.ts +2 -1
- package/src/ui-action-plugin.ts +2 -0
- package/src/ui-page-plugin.ts +34 -8
- package/src/ui-policy-plugin.ts +2 -1
- package/src/user-preference-plugin.ts +2 -0
- package/src/utils.ts +42 -2
- package/src/ux-list-menu-config-plugin.ts +2 -0
- package/src/view-plugin.ts +1 -0
- package/src/workspace-plugin.ts +2 -0
- package/src/_types/eslint-plugin-es-x.d.ts +0 -17
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a Date object to ServiceNow UTC datetime format (YYYY-MM-DD HH:MM:SS)
|
|
3
|
+
* @param date - The Date object to format (defaults to current time)
|
|
4
|
+
* @returns Formatted UTC datetime string
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const formatted = formatToUTC(new Date());
|
|
8
|
+
* // Returns: '1970-01-01 09:45:00'
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const formatted = formatToUTC();
|
|
12
|
+
* // Returns current time in UTC: '2026-02-27 07:43:00'
|
|
13
|
+
*/
|
|
14
|
+
export function formatToUTC(date: Date = new Date()): string {
|
|
15
|
+
const year = date.getUTCFullYear()
|
|
16
|
+
const month = String(date.getUTCMonth() + 1).padStart(2, '0')
|
|
17
|
+
const day = String(date.getUTCDate()).padStart(2, '0')
|
|
18
|
+
const hour = String(date.getUTCHours()).padStart(2, '0')
|
|
19
|
+
const minute = String(date.getUTCMinutes()).padStart(2, '0')
|
|
20
|
+
const second = String(date.getUTCSeconds()).padStart(2, '0')
|
|
21
|
+
|
|
22
|
+
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Converts a datetime string from a specified timezone to UTC.
|
|
27
|
+
* Similar to timeFieldToXML but handles full date and time, not just time of day.
|
|
28
|
+
*
|
|
29
|
+
* @param dateTimeStr - DateTime string in format 'YYYY-MM-DD HH:MM:SS'
|
|
30
|
+
* @param timeZone - Optional IANA timezone string (e.g., 'America/New_York', 'Asia/Kolkata'). Defaults to system timezone.
|
|
31
|
+
* @returns Formatted UTC datetime string in 'YYYY-MM-DD HH:MM:SS' format
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Convert '2026-03-02 14:30:00' from IST to UTC
|
|
35
|
+
* const utcDate = dateTimeFieldToXML('2026-03-02 14:30:00', 'Asia/Kolkata')
|
|
36
|
+
* // Returns '2026-03-02 09:00:00'
|
|
37
|
+
*/
|
|
38
|
+
export function dateTimeFieldToXML(dateTimeStr: string, timeZone?: string): string {
|
|
39
|
+
// Parse the datetime string
|
|
40
|
+
const match = dateTimeStr.match(/^(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})$/)
|
|
41
|
+
if (!match) {
|
|
42
|
+
throw new Error(`Invalid datetime format: ${dateTimeStr}. Expected format: YYYY-MM-DD HH:MM:SS`)
|
|
43
|
+
}
|
|
44
|
+
// If timezone is 'floating' or not provided, use system timezone
|
|
45
|
+
const targetTimeZone =
|
|
46
|
+
timeZone === 'floating' || !timeZone ? Intl.DateTimeFormat().resolvedOptions().timeZone : timeZone
|
|
47
|
+
|
|
48
|
+
if (targetTimeZone === 'GMT' || targetTimeZone === 'UTC') {
|
|
49
|
+
return dateTimeStr
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const year = parseInt(match[1]!, 10)
|
|
53
|
+
const month = parseInt(match[2]!, 10)
|
|
54
|
+
const day = parseInt(match[3]!, 10)
|
|
55
|
+
const hours = parseInt(match[4]!, 10)
|
|
56
|
+
const minutes = parseInt(match[5]!, 10)
|
|
57
|
+
const seconds = parseInt(match[6]!, 10)
|
|
58
|
+
|
|
59
|
+
const padZero = (n: number) => String(n).padStart(2, '0')
|
|
60
|
+
|
|
61
|
+
// Convert from specified timezone to UTC
|
|
62
|
+
// Create a reference date to calculate the timezone offset
|
|
63
|
+
const localDateStr = `${year}-${padZero(month)}-${padZero(day)}T${padZero(hours)}:${padZero(minutes)}:${padZero(seconds)}`
|
|
64
|
+
|
|
65
|
+
// Create a Date treating the input as UTC first
|
|
66
|
+
const utcDate = new Date(`${localDateStr}Z`)
|
|
67
|
+
|
|
68
|
+
// Get what this UTC time looks like in the target timezone
|
|
69
|
+
const formatter = new Intl.DateTimeFormat('en-US', {
|
|
70
|
+
timeZone: targetTimeZone,
|
|
71
|
+
year: 'numeric',
|
|
72
|
+
month: '2-digit',
|
|
73
|
+
day: '2-digit',
|
|
74
|
+
hour: '2-digit',
|
|
75
|
+
minute: '2-digit',
|
|
76
|
+
second: '2-digit',
|
|
77
|
+
hour12: false,
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const parts = formatter.formatToParts(utcDate)
|
|
81
|
+
const dateParts: Record<string, string> = {}
|
|
82
|
+
|
|
83
|
+
parts.forEach((part) => {
|
|
84
|
+
if (part.type !== 'literal') {
|
|
85
|
+
dateParts[part.type] = part.value
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// Calculate the difference between what we want and what we got
|
|
90
|
+
const targetYear = parseInt(dateParts['year']!, 10)
|
|
91
|
+
const targetMonth = parseInt(dateParts['month']!, 10)
|
|
92
|
+
const targetDay = parseInt(dateParts['day']!, 10)
|
|
93
|
+
const targetHour = parseInt(dateParts['hour']!, 10)
|
|
94
|
+
const targetMinute = parseInt(dateParts['minute']!, 10)
|
|
95
|
+
const targetSecond = parseInt(dateParts['second']!, 10)
|
|
96
|
+
|
|
97
|
+
// Calculate the offset in milliseconds
|
|
98
|
+
const wantedTime = new Date(year, month - 1, day, hours, minutes, seconds).getTime()
|
|
99
|
+
const gotTime = new Date(targetYear, targetMonth - 1, targetDay, targetHour, targetMinute, targetSecond).getTime()
|
|
100
|
+
const offset = gotTime - wantedTime
|
|
101
|
+
|
|
102
|
+
// Apply the offset to get the correct UTC time
|
|
103
|
+
const resultDate = new Date(utcDate.getTime() - offset)
|
|
104
|
+
return formatToUTC(resultDate)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Converts an XML datetime string (in UTC) to a datetime string in a specified timezone
|
|
109
|
+
* @param utcDateTimeStr - UTC datetime string in format 'YYYY-MM-DD HH:MM:SS'
|
|
110
|
+
* @param timeZone - Optional IANA timezone string (e.g., 'America/New_York', 'Asia/Kolkata'). If not provided, returns the UTC string as-is.
|
|
111
|
+
* @returns Datetime string in the specified timezone in 'YYYY-MM-DD HH:MM:SS' format
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* // Convert '2026-03-02 09:00:00' UTC to IST
|
|
115
|
+
* const localDateTime = convertXMLToDateTime('2026-03-02 09:00:00', 'Asia/Kolkata')
|
|
116
|
+
* // Returns '2026-03-02 14:30:00'
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* // Without timezone, returns the UTC string as-is
|
|
120
|
+
* const utcDateTime = convertXMLToDateTime('2026-03-02 09:00:00')
|
|
121
|
+
* // Returns '2026-03-02 09:00:00'
|
|
122
|
+
*/
|
|
123
|
+
export function convertXMLToDateTime(utcDateTimeStr: string, timeZone?: string): string {
|
|
124
|
+
// Parse the UTC datetime string
|
|
125
|
+
const match = utcDateTimeStr.match(/^(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})$/)
|
|
126
|
+
if (!match) {
|
|
127
|
+
throw new Error(`Invalid datetime format: ${utcDateTimeStr}. Expected format: YYYY-MM-DD HH:MM:SS`)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// If timezone is 'floating' or not provided, use system timezone
|
|
131
|
+
const targetTimeZone =
|
|
132
|
+
timeZone === 'floating' || !timeZone ? Intl.DateTimeFormat().resolvedOptions().timeZone : timeZone
|
|
133
|
+
|
|
134
|
+
if (targetTimeZone === 'GMT' || targetTimeZone === 'UTC') {
|
|
135
|
+
return utcDateTimeStr
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const year = parseInt(match[1]!, 10)
|
|
139
|
+
const month = parseInt(match[2]!, 10)
|
|
140
|
+
const day = parseInt(match[3]!, 10)
|
|
141
|
+
const hours = parseInt(match[4]!, 10)
|
|
142
|
+
const minutes = parseInt(match[5]!, 10)
|
|
143
|
+
const seconds = parseInt(match[6]!, 10)
|
|
144
|
+
|
|
145
|
+
// Create a Date object from the UTC datetime
|
|
146
|
+
const utcDate = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds))
|
|
147
|
+
|
|
148
|
+
// Format the date in the target timezone
|
|
149
|
+
const formatter = new Intl.DateTimeFormat('en-US', {
|
|
150
|
+
timeZone: targetTimeZone,
|
|
151
|
+
year: 'numeric',
|
|
152
|
+
month: '2-digit',
|
|
153
|
+
day: '2-digit',
|
|
154
|
+
hour: '2-digit',
|
|
155
|
+
minute: '2-digit',
|
|
156
|
+
second: '2-digit',
|
|
157
|
+
hour12: false,
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
const parts = formatter.formatToParts(utcDate)
|
|
161
|
+
const dateParts: Record<string, string> = {}
|
|
162
|
+
|
|
163
|
+
parts.forEach((part) => {
|
|
164
|
+
if (part.type !== 'literal') {
|
|
165
|
+
dateParts[part.type] = part.value
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
return `${dateParts['year']}-${dateParts['month']}-${dateParts['day']} ${dateParts['hour']}:${dateParts['minute']}:${dateParts['second']}`
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Formats time data (hours, minutes, seconds) as a datetime string without timezone conversion.
|
|
174
|
+
* Used for storing the original user-entered time value in the 'entered_time' field.
|
|
175
|
+
*
|
|
176
|
+
* @param timeData - Object containing hours, minutes, and seconds
|
|
177
|
+
* @returns Formatted datetime string in 'YYYY-MM-DD HH:MM:SS' format with epoch date (1970-01-01)
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* formatTimeDataToDateTime({ hours: 14, minutes: 30, seconds: 0 })
|
|
181
|
+
* // Returns '1970-01-01 14:30:00'
|
|
182
|
+
*/
|
|
183
|
+
export function formatTimeDataToDateTime(timeData: { hours?: number; minutes?: number; seconds?: number }): string {
|
|
184
|
+
const hours = String(timeData.hours || 0).padStart(2, '0')
|
|
185
|
+
const minutes = String(timeData.minutes || 0).padStart(2, '0')
|
|
186
|
+
const seconds = String(timeData.seconds || 0).padStart(2, '0')
|
|
187
|
+
return `1970-01-01 ${hours}:${minutes}:${seconds}`
|
|
188
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { CallExpressionShape, Plugin } from '@servicenow/sdk-build-core'
|
|
2
2
|
import { NowIdShape } from './now-id-plugin'
|
|
3
3
|
import { ModuleFunctionShape } from './server-module-plugin'
|
|
4
|
+
import { createSdkDocEntry } from './utils'
|
|
4
5
|
|
|
5
6
|
export const ScriptActionPlugin = Plugin.create({
|
|
6
7
|
name: 'ScriptActionPlugin',
|
|
8
|
+
docs: [createSdkDocEntry('ScriptAction', ['sysevent_script_action'])],
|
|
7
9
|
records: {
|
|
8
10
|
sysevent_script_action: {
|
|
9
11
|
toShape(record) {
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { CallExpressionShape, isSNScope, Plugin } from '@servicenow/sdk-build-core'
|
|
2
2
|
import { NowIdShape } from './now-id-plugin'
|
|
3
3
|
import { NowIncludeShape } from './now-include-plugin'
|
|
4
|
+
import { createSdkDocEntry } from './utils'
|
|
4
5
|
|
|
5
6
|
const nameRegex = /^[a-zA-Z_$][0-9a-zA-Z_$]+$/
|
|
6
7
|
|
|
7
8
|
export const ScriptIncludePlugin = Plugin.create({
|
|
8
9
|
name: `ScriptIncludePlugin`,
|
|
10
|
+
docs: [createSdkDocEntry('ScriptInclude', ['sys_script_include'])],
|
|
9
11
|
records: {
|
|
10
12
|
sys_script_include: {
|
|
11
13
|
async toShape(record, { transform }) {
|
|
@@ -351,6 +351,7 @@ function getModuleDependencyPath(
|
|
|
351
351
|
|
|
352
352
|
export const ServerModulePlugin = Plugin.create({
|
|
353
353
|
name: 'ServerModulePlugin',
|
|
354
|
+
docs: [],
|
|
354
355
|
files: [
|
|
355
356
|
{
|
|
356
357
|
entryPoint: true,
|
|
@@ -432,6 +433,16 @@ export const ServerModulePlugin = Plugin.create({
|
|
|
432
433
|
return { success: false }
|
|
433
434
|
}
|
|
434
435
|
|
|
436
|
+
// Lint local module for Rhino compatibility (no Glide restrictions)
|
|
437
|
+
if (/\.(js|cjs|mjs|ts)$/.test(pathModule.extname(resolvedPath))) {
|
|
438
|
+
const { LocalModuleLint } = await import('../repack/lint/index.js')
|
|
439
|
+
const lint = new LocalModuleLint()
|
|
440
|
+
const lintResult = lint.check(content)
|
|
441
|
+
if (lintResult) {
|
|
442
|
+
diagnostics.error(file, `Unsupported APIs detected in module:\n${lintResult}`)
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
435
446
|
const relativePath = pathModule.relative(project.getRootDir(), resolvedPath)
|
|
436
447
|
const sysModulePath = NowConfig.moduleResolutionPath(config, packageJson, false, relativePath)
|
|
437
448
|
|
|
@@ -487,6 +498,7 @@ export const ServerModulePlugin = Plugin.create({
|
|
|
487
498
|
|
|
488
499
|
const modules: { id: string; path: string; content: string }[] = []
|
|
489
500
|
const { Lint } = await import('../repack/lint/index.js')
|
|
501
|
+
const lint = new Lint()
|
|
490
502
|
for (const node of dependencyNodes) {
|
|
491
503
|
const { packagePath, files, updatedManifest, originalPath } = node
|
|
492
504
|
const { name, version } = updatedManifest
|
|
@@ -499,8 +511,8 @@ export const ServerModulePlugin = Plugin.create({
|
|
|
499
511
|
)
|
|
500
512
|
for (const file of files) {
|
|
501
513
|
const fileContent = fs.readFileSync(pathModule.join(packagePath, file)).toString('utf-8')
|
|
502
|
-
if (
|
|
503
|
-
const result =
|
|
514
|
+
if (/\.(js|cjs|mjs)$/.test(pathModule.extname(file))) {
|
|
515
|
+
const result = lint.check(fileContent)
|
|
504
516
|
if (result) {
|
|
505
517
|
logger.warn(`Use of unsupported APIs detected in npm dependency ${name}`)
|
|
506
518
|
logger.warn(result)
|
|
@@ -11,9 +11,11 @@ import {
|
|
|
11
11
|
resolveAndValidateVariableId,
|
|
12
12
|
} from './utils'
|
|
13
13
|
import { validateCatalogItemVariableSetExclusivity } from './service-catalog-diagnostics'
|
|
14
|
+
import { createSdkDocEntry } from '../utils'
|
|
14
15
|
|
|
15
16
|
export const CatalogClientScriptPlugin = Plugin.create({
|
|
16
17
|
name: 'CatalogClientScriptPlugin',
|
|
18
|
+
docs: [createSdkDocEntry('CatalogClientScript', ['catalog_script_client'])],
|
|
17
19
|
records: {
|
|
18
20
|
catalog_script_client: {
|
|
19
21
|
async toShape(record, { database, transform }) {
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
createScript,
|
|
15
15
|
} from './utils'
|
|
16
16
|
import { validateFulfillmentProcessExclusivity, validateCategoriesRequireCatalogs } from './service-catalog-diagnostics'
|
|
17
|
+
import { createSdkDocEntry } from '../utils'
|
|
17
18
|
import {
|
|
18
19
|
buildVariablesSchema,
|
|
19
20
|
CatalogItemBaseRelationships,
|
|
@@ -27,6 +28,7 @@ import {
|
|
|
27
28
|
|
|
28
29
|
export const CatalogItemPlugin = Plugin.create({
|
|
29
30
|
name: 'CatalogItemPlugin',
|
|
31
|
+
docs: [createSdkDocEntry('CatalogItem', ['sc_cat_item'])],
|
|
30
32
|
records: {
|
|
31
33
|
sc_cat_item: {
|
|
32
34
|
relationships: CatalogItemBaseRelationships,
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
getValueActionToDb,
|
|
26
26
|
} from './utils'
|
|
27
27
|
import { validateCatalogItemVariableSetExclusivity, validateUiPolicyActionMessage } from './service-catalog-diagnostics'
|
|
28
|
+
import { createSdkDocEntry } from '../utils'
|
|
28
29
|
|
|
29
30
|
// Define table names as constants since they're not exported from the core tables
|
|
30
31
|
const CATALOG_UI_POLICY = 'catalog_ui_policy'
|
|
@@ -50,6 +51,7 @@ const stripIOPrefix = (value: string): string => {
|
|
|
50
51
|
|
|
51
52
|
export const CatalogUiPolicyPlugin = Plugin.create({
|
|
52
53
|
name: 'CatalogUiPolicyPlugin',
|
|
54
|
+
docs: [createSdkDocEntry('CatalogUiPolicy', ['catalog_ui_policy'])],
|
|
53
55
|
records: {
|
|
54
56
|
[CATALOG_UI_POLICY]: {
|
|
55
57
|
relationships: {
|
|
@@ -28,9 +28,11 @@ import {
|
|
|
28
28
|
} from './service-catalog-base'
|
|
29
29
|
import { validateFulfillmentProcessExclusivity, validateCategoriesRequireCatalogs } from './service-catalog-diagnostics'
|
|
30
30
|
import { ModuleFunctionShape } from '../server-module-plugin'
|
|
31
|
+
import { createSdkDocEntry } from '../utils'
|
|
31
32
|
|
|
32
33
|
export const CatalogItemRecordProducerPlugin = Plugin.create({
|
|
33
34
|
name: 'CatalogItemRecordProducerPlugin',
|
|
35
|
+
docs: [createSdkDocEntry('CatalogItemRecordProducer', ['sc_cat_item_producer'])],
|
|
34
36
|
records: {
|
|
35
37
|
sc_cat_item_producer: {
|
|
36
38
|
relationships: CatalogItemBaseRelationships,
|
|
@@ -156,6 +156,36 @@ export function validateMandatoryReadOnlyHidden(config: ObjectShape, diagnostics
|
|
|
156
156
|
return true
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Validates that selectionRequired is not true when hidden or readOnly is true, and vice versa.
|
|
161
|
+
* This is specific to Checkbox variables which use selectionRequired instead of mandatory.
|
|
162
|
+
* Returns true if valid, false if a diagnostic was emitted.
|
|
163
|
+
*/
|
|
164
|
+
export function validateSelectionRequiredReadOnlyHidden(config: ObjectShape, diagnostics: Diagnostics): boolean {
|
|
165
|
+
const isSelectionRequired =
|
|
166
|
+
config.get('selectionRequired').isDefined() && config.get('selectionRequired').ifBoolean()?.getValue() === true
|
|
167
|
+
const isReadOnly = config.get('readOnly').isDefined() && config.get('readOnly').ifBoolean()?.getValue() === true
|
|
168
|
+
const isHidden = config.get('hidden').isDefined() && config.get('hidden').ifBoolean()?.getValue() === true
|
|
169
|
+
|
|
170
|
+
if (isSelectionRequired && isReadOnly) {
|
|
171
|
+
diagnostics.error(
|
|
172
|
+
config.get('selectionRequired'),
|
|
173
|
+
`'selectionRequired' cannot be true when 'readOnly' is true. A checkbox cannot be both required and read-only.`
|
|
174
|
+
)
|
|
175
|
+
return false
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (isSelectionRequired && isHidden) {
|
|
179
|
+
diagnostics.error(
|
|
180
|
+
config.get('selectionRequired'),
|
|
181
|
+
`'selectionRequired' cannot be true when 'hidden' is true. A checkbox cannot be both required and hidden.`
|
|
182
|
+
)
|
|
183
|
+
return false
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return true
|
|
187
|
+
}
|
|
188
|
+
|
|
159
189
|
/**
|
|
160
190
|
* Validates lookup variable configuration: table-based and choice-based properties are mutually exclusive,
|
|
161
191
|
* and price fields are not allowed when uniqueValuesOnly is true.
|
|
@@ -11,6 +11,7 @@ import { convertRolesToString, getVisibilityId, validateFieldNameBelongsToTable
|
|
|
11
11
|
import {
|
|
12
12
|
validateMapToFieldRequiresField,
|
|
13
13
|
validateMandatoryReadOnlyHidden,
|
|
14
|
+
validateSelectionRequiredReadOnlyHidden,
|
|
14
15
|
validateLookupSourceExclusivity,
|
|
15
16
|
validateReferenceQualifierExclusivity,
|
|
16
17
|
} from './service-catalog-diagnostics'
|
|
@@ -59,7 +60,9 @@ export async function buildVariableRecords(options: {
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
// Validate mandatory/readOnly/hidden consistency (applies to interactive variables)
|
|
62
|
-
if (
|
|
63
|
+
if (calleeName === VariableTypeName.CHECKBOX) {
|
|
64
|
+
validateSelectionRequiredReadOnlyHidden(config, diagnostics)
|
|
65
|
+
} else if (
|
|
63
66
|
calleeName !== VariableTypeName.BREAK &&
|
|
64
67
|
calleeName !== VariableTypeName.CONTAINER_END &&
|
|
65
68
|
calleeName !== VariableTypeName.CONTAINER_SPLIT &&
|
|
@@ -112,7 +115,10 @@ export async function buildVariableRecords(options: {
|
|
|
112
115
|
question_text: $.from('question').def(''),
|
|
113
116
|
order: $.def(0),
|
|
114
117
|
active: $.from('active').toBoolean().def(true),
|
|
115
|
-
mandatory:
|
|
118
|
+
mandatory:
|
|
119
|
+
calleeName === VariableTypeName.CHECKBOX
|
|
120
|
+
? $.from('selectionRequired').toBoolean().def(false)
|
|
121
|
+
: $.from('mandatory').toBoolean().def(false),
|
|
116
122
|
read_only: $.from('readOnly').toBoolean().def(false),
|
|
117
123
|
hidden: $.from('hidden').toBoolean().def(false),
|
|
118
124
|
disable_initial_slot_fill: $.from('disableInitialSlotFill').toBoolean().def(false),
|
|
@@ -20,9 +20,11 @@ import {
|
|
|
20
20
|
getVariableSetTypeFromDb,
|
|
21
21
|
getVariableSetTypeToDb,
|
|
22
22
|
} from './utils'
|
|
23
|
+
import { createSdkDocEntry } from '../utils'
|
|
23
24
|
|
|
24
25
|
export const VariableSetPlugin = Plugin.create({
|
|
25
26
|
name: 'VariableSetPlugin',
|
|
27
|
+
docs: [createSdkDocEntry('VariableSet', ['item_option_new_set'])],
|
|
26
28
|
records: {
|
|
27
29
|
item_option_new_set: {
|
|
28
30
|
relationships: {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { CallExpressionShape, Plugin } from '@servicenow/sdk-build-core'
|
|
2
2
|
import { NowIdShape } from '../now-id-plugin'
|
|
3
|
+
import { createSdkDocEntry } from '../utils'
|
|
3
4
|
|
|
4
5
|
export const SPAngularProviderPlugin = Plugin.create({
|
|
5
6
|
name: 'SPAngularProviderPlugin',
|
|
7
|
+
docs: [createSdkDocEntry('SPAngularProvider', ['sp_angular_provider'])],
|
|
6
8
|
records: {
|
|
7
9
|
sp_angular_provider: {
|
|
8
10
|
relationships: {
|
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CallExpressionShape,
|
|
3
|
-
type Diagnostics,
|
|
4
|
-
type Factory,
|
|
5
|
-
Plugin,
|
|
6
|
-
type Record,
|
|
7
|
-
type Shape,
|
|
8
|
-
type RecordId,
|
|
9
|
-
} from '@servicenow/sdk-build-core'
|
|
1
|
+
import { CallExpressionShape, Plugin } from '@servicenow/sdk-build-core'
|
|
10
2
|
import { toReference } from '../utils'
|
|
11
3
|
import { NowIdShape } from '../now-id-plugin'
|
|
4
|
+
import { createSdkDocEntry } from '../utils'
|
|
5
|
+
import { getIncludeRecords } from './utils'
|
|
12
6
|
|
|
13
7
|
export const SPWidgetDependencyPlugin = Plugin.create({
|
|
14
8
|
name: 'SPWidgetDependencyPlugin',
|
|
9
|
+
docs: [createSdkDocEntry('SPWidgetDependency', ['sp_dependency'])],
|
|
15
10
|
records: {
|
|
16
11
|
sp_dependency: {
|
|
17
12
|
relationships: {
|
|
@@ -217,6 +212,7 @@ export const SPWidgetDependencyPlugin = Plugin.create({
|
|
|
217
212
|
factory,
|
|
218
213
|
'm2m_sp_dependency_css_include',
|
|
219
214
|
'sp_css_include',
|
|
215
|
+
'sp_dependency',
|
|
220
216
|
diagnostics
|
|
221
217
|
)
|
|
222
218
|
|
|
@@ -226,6 +222,7 @@ export const SPWidgetDependencyPlugin = Plugin.create({
|
|
|
226
222
|
factory,
|
|
227
223
|
'm2m_sp_dependency_js_include',
|
|
228
224
|
'sp_js_include',
|
|
225
|
+
'sp_dependency',
|
|
229
226
|
diagnostics
|
|
230
227
|
)
|
|
231
228
|
|
|
@@ -237,47 +234,3 @@ export const SPWidgetDependencyPlugin = Plugin.create({
|
|
|
237
234
|
},
|
|
238
235
|
],
|
|
239
236
|
})
|
|
240
|
-
|
|
241
|
-
async function getIncludeRecords(
|
|
242
|
-
shape: Shape,
|
|
243
|
-
dependencyId: Shape,
|
|
244
|
-
factory: Factory,
|
|
245
|
-
m2mTable: string,
|
|
246
|
-
includeTable: string,
|
|
247
|
-
diagnostics: Diagnostics
|
|
248
|
-
) {
|
|
249
|
-
return (
|
|
250
|
-
await Promise.all(
|
|
251
|
-
shape?.ifArray()?.map(async (include) => {
|
|
252
|
-
const includeProps = include.ifObject()?.get('include')
|
|
253
|
-
|
|
254
|
-
let includeId: string | RecordId
|
|
255
|
-
if (includeProps?.isString()) {
|
|
256
|
-
includeId = includeProps.toString().getValue()
|
|
257
|
-
} else if (includeProps?.isRecord()) {
|
|
258
|
-
includeId = includeProps.getId()
|
|
259
|
-
} else {
|
|
260
|
-
const necessaryPlugin = includeTable === 'sp_js_include' ? 'JsInclude' : 'CssInclude'
|
|
261
|
-
diagnostics.error(
|
|
262
|
-
includeProps!,
|
|
263
|
-
`include must contain a valid ${necessaryPlugin}, Record<'${includeTable}'> or sys_id'`
|
|
264
|
-
)
|
|
265
|
-
return undefined
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const m2mProps = {
|
|
269
|
-
[includeTable]: includeId,
|
|
270
|
-
sp_dependency: dependencyId,
|
|
271
|
-
}
|
|
272
|
-
return await factory.createRecord({
|
|
273
|
-
source: shape,
|
|
274
|
-
table: m2mTable,
|
|
275
|
-
properties: {
|
|
276
|
-
order: include.ifObject()?.get('order').asNumber().getValue() || 100,
|
|
277
|
-
...m2mProps,
|
|
278
|
-
},
|
|
279
|
-
})
|
|
280
|
-
}) ?? []
|
|
281
|
-
)
|
|
282
|
-
).filter((rec) => rec) as Record[]
|
|
283
|
-
}
|