@servicenow/sdk 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +24 -0
  2. package/bin/debug.js +3 -0
  3. package/bin/index.js +2 -0
  4. package/dist/auth/index.d.ts +11 -0
  5. package/dist/auth/index.js +206 -0
  6. package/dist/auth/index.js.map +1 -0
  7. package/dist/auth/keychain/index.d.ts +12 -0
  8. package/dist/auth/keychain/index.js +44 -0
  9. package/dist/auth/keychain/index.js.map +1 -0
  10. package/dist/command/auth/commands/clear.d.ts +6 -0
  11. package/dist/command/auth/commands/clear.js +30 -0
  12. package/dist/command/auth/commands/clear.js.map +1 -0
  13. package/dist/command/auth/commands/list.d.ts +6 -0
  14. package/dist/command/auth/commands/list.js +30 -0
  15. package/dist/command/auth/commands/list.js.map +1 -0
  16. package/dist/command/auth/commands/save.d.ts +10 -0
  17. package/dist/command/auth/commands/save.js +96 -0
  18. package/dist/command/auth/commands/save.js.map +1 -0
  19. package/dist/command/auth/commands/setDefault.d.ts +6 -0
  20. package/dist/command/auth/commands/setDefault.js +30 -0
  21. package/dist/command/auth/commands/setDefault.js.map +1 -0
  22. package/dist/command/auth/commands/validate.d.ts +6 -0
  23. package/dist/command/auth/commands/validate.js +43 -0
  24. package/dist/command/auth/commands/validate.js.map +1 -0
  25. package/dist/command/auth/index.d.ts +2 -0
  26. package/dist/command/auth/index.js +35 -0
  27. package/dist/command/auth/index.js.map +1 -0
  28. package/dist/command/build/index.d.ts +11 -0
  29. package/dist/command/build/index.js +98 -0
  30. package/dist/command/build/index.js.map +1 -0
  31. package/dist/command/clean/index.d.ts +6 -0
  32. package/dist/command/clean/index.js +34 -0
  33. package/dist/command/clean/index.js.map +1 -0
  34. package/dist/command/compile/index.d.ts +7 -0
  35. package/dist/command/compile/index.js +42 -0
  36. package/dist/command/compile/index.js.map +1 -0
  37. package/dist/command/convert/index.d.ts +12 -0
  38. package/dist/command/convert/index.js +77 -0
  39. package/dist/command/convert/index.js.map +1 -0
  40. package/dist/command/create/index.d.ts +15 -0
  41. package/dist/command/create/index.js +92 -0
  42. package/dist/command/create/index.js.map +1 -0
  43. package/dist/command/deploy/index.d.ts +12 -0
  44. package/dist/command/deploy/index.js +80 -0
  45. package/dist/command/deploy/index.js.map +1 -0
  46. package/dist/command/fetch/index.d.ts +12 -0
  47. package/dist/command/fetch/index.js +78 -0
  48. package/dist/command/fetch/index.js.map +1 -0
  49. package/dist/command/generate-modules/index.d.ts +7 -0
  50. package/dist/command/generate-modules/index.js +46 -0
  51. package/dist/command/generate-modules/index.js.map +1 -0
  52. package/dist/command/pack/index.d.ts +6 -0
  53. package/dist/command/pack/index.js +40 -0
  54. package/dist/command/pack/index.js.map +1 -0
  55. package/dist/command/package-dependencies/index.d.ts +8 -0
  56. package/dist/command/package-dependencies/index.js +52 -0
  57. package/dist/command/package-dependencies/index.js.map +1 -0
  58. package/dist/command/test/index.d.ts +3 -0
  59. package/dist/command/test/index.js +52 -0
  60. package/dist/command/test/index.js.map +1 -0
  61. package/dist/command/transform/index.d.ts +3 -0
  62. package/dist/command/transform/index.js +63 -0
  63. package/dist/command/transform/index.js.map +1 -0
  64. package/dist/epilogue/index.d.ts +1 -0
  65. package/dist/epilogue/index.js +9 -0
  66. package/dist/epilogue/index.js.map +1 -0
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.js +55 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/usage/index.d.ts +1 -0
  71. package/dist/usage/index.js +16 -0
  72. package/dist/usage/index.js.map +1 -0
  73. package/dist/util.d.ts +1 -0
  74. package/dist/util.js +25 -0
  75. package/dist/util.js.map +1 -0
  76. package/license +9 -0
  77. package/package.json +42 -0
  78. package/src/auth/index.ts +238 -0
  79. package/src/auth/keychain/index.ts +23 -0
  80. package/src/command/auth/commands/clear.ts +21 -0
  81. package/src/command/auth/commands/list.ts +21 -0
  82. package/src/command/auth/commands/save.ts +100 -0
  83. package/src/command/auth/commands/setDefault.ts +21 -0
  84. package/src/command/auth/commands/validate.ts +35 -0
  85. package/src/command/auth/index.ts +24 -0
  86. package/src/command/build/index.ts +96 -0
  87. package/src/command/clean/index.ts +22 -0
  88. package/src/command/compile/index.ts +31 -0
  89. package/src/command/convert/index.ts +76 -0
  90. package/src/command/create/index.ts +97 -0
  91. package/src/command/deploy/index.ts +84 -0
  92. package/src/command/fetch/index.ts +78 -0
  93. package/src/command/generate-modules/index.ts +36 -0
  94. package/src/command/pack/index.ts +27 -0
  95. package/src/command/package-dependencies/index.ts +43 -0
  96. package/src/command/test/index.ts +40 -0
  97. package/src/command/transform/index.ts +45 -0
  98. package/src/epilogue/index.ts +5 -0
  99. package/src/index.ts +50 -0
  100. package/src/usage/index.ts +13 -0
  101. package/src/util.ts +21 -0
@@ -0,0 +1,238 @@
1
+ import { logger } from '@servicenow/sdk-cli-core/dist/cli-util/logger'
2
+ import { Creds } from '@servicenow/sdk-cli-core/dist/command/login'
3
+ import { NowSDKError } from '@servicenow/sdk-cli-core/dist/cli-util/Error'
4
+ import { KeyChain } from './keychain'
5
+ import chalk from 'chalk'
6
+ import { TEST_COMMAND } from '../command/test'
7
+
8
+ export const SERVICE = 'fluent'
9
+ const DEFAULT_ALIAS = 'fluent-default'
10
+
11
+ const keychain = new KeyChain(SERVICE)
12
+
13
+ export interface StoredCredential extends Creds {
14
+ isDefault: boolean
15
+ alias: string
16
+ }
17
+
18
+ type CredentialPreview = Omit<StoredCredential, 'password' | 'alias'>
19
+
20
+ export async function getCredentials(args: any): Promise<Creds> {
21
+ const [command] = args._
22
+ let credentials: Creds | undefined
23
+ if (command === TEST_COMMAND) {
24
+ credentials = { username: args.username!, password: args.password!, host: args.host! }
25
+ } else {
26
+ credentials = await getStoredCredentials(args.auth)
27
+ }
28
+ return credentials
29
+ }
30
+
31
+ async function getStoredCredentials(alias: string = DEFAULT_ALIAS): Promise<Creds> {
32
+ if (alias === DEFAULT_ALIAS) {
33
+ const defaultCreds = await getDefaultCredentials()
34
+ if (!defaultCreds) {
35
+ throw new NowSDKError(
36
+ 'Default Credential has not been set, Please provide the credential alias to use or set a default by using "$now-sdk auth set-default" command',
37
+ { command: 'login', type: 'credential_storage' }
38
+ )
39
+ }
40
+ }
41
+
42
+ const keyStore = await keychain.getPassword(alias)
43
+ if (!keyStore) {
44
+ throw new NowSDKError(
45
+ `Could not find stored credentials for alias: ${alias}, Please check the alias provided or save an alias using "$now-sdk auth save" command`,
46
+ { command: 'login', type: 'credential_storage' }
47
+ )
48
+ }
49
+
50
+ return JSON.parse(keyStore) as Creds
51
+ }
52
+
53
+ export async function storeCredentials(
54
+ alias: string,
55
+ host: string,
56
+ username: string,
57
+ password: string,
58
+ isDefault: boolean
59
+ ): Promise<void> {
60
+ host = getOrigin(host)
61
+
62
+ const defaultCreds = await getDefaultCredentials()
63
+
64
+ // if no default is set, set the current alias as default
65
+ if (!defaultCreds || defaultCreds.alias === alias) {
66
+ isDefault = true
67
+ }
68
+
69
+ const creds: StoredCredential = {
70
+ username,
71
+ password,
72
+ host,
73
+ isDefault,
74
+ alias,
75
+ }
76
+
77
+ await keychain.setPassword(alias, JSON.stringify(creds))
78
+
79
+ if (isDefault) {
80
+ await updateDefaultCredential(alias, defaultCreds)
81
+ }
82
+ }
83
+
84
+ export async function updateDefaultCredential(alias: string, defaultCreds?: StoredCredential) {
85
+ logger.info(`Setting alias ${alias} as default ...`)
86
+ const keyStore = await keychain.getPassword(alias)
87
+ if (!keyStore) {
88
+ throw new NowSDKError(
89
+ `No credentials found for alias ${alias}, Please check the alias provided or save an alias using "$now-sdk auth save" command`,
90
+ { command: 'auth', type: 'credential_storage' }
91
+ )
92
+ }
93
+
94
+ defaultCreds = defaultCreds ?? (await getDefaultCredentials())
95
+
96
+ if (defaultCreds) {
97
+ const { alias: defaultCredAlias } = defaultCreds
98
+
99
+ if (defaultCredAlias === alias) {
100
+ logger.info(`alias ${alias} is already set as default`)
101
+ return
102
+ }
103
+
104
+ defaultCreds.isDefault = false
105
+ keychain.setPassword(defaultCredAlias, JSON.stringify(defaultCreds))
106
+ }
107
+
108
+ const creds: StoredCredential = JSON.parse(keyStore as string)
109
+ creds.isDefault = true
110
+ keychain.setPassword(DEFAULT_ALIAS, JSON.stringify(creds))
111
+ keychain.setPassword(alias, JSON.stringify(creds))
112
+ logger.info(`Successfully set alias ${alias} as default`)
113
+ }
114
+
115
+ async function getDefaultCredentials(): Promise<StoredCredential | undefined> {
116
+ const keyStore = await keychain.getPassword(DEFAULT_ALIAS)
117
+ if (!keyStore) {
118
+ return
119
+ }
120
+
121
+ return JSON.parse(keyStore) as StoredCredential
122
+ }
123
+
124
+ export async function removeCredentials(alias: string): Promise<void> {
125
+ if (process.env['NODE_ENV'] === 'test') {
126
+ return
127
+ }
128
+
129
+ if (alias === 'all') {
130
+ logger.info(`Removing all stored credentials ...`)
131
+ const credentials = await keychain.findCredentials()
132
+ if (!credentials || credentials.length === 0) {
133
+ return
134
+ }
135
+
136
+ for (const credential of credentials) {
137
+ await keychain.deletePassword(credential.account)
138
+ }
139
+ logger.info(`Successfully removed all stored credentials`)
140
+ return
141
+ }
142
+
143
+ logger.info(`Removing credentials for alias: ${alias} ...`)
144
+
145
+ const keyStore = await keychain.getPassword(alias)
146
+
147
+ if (!keyStore) {
148
+ logger.info(`No credentials found for alias: ${alias}`)
149
+ return
150
+ }
151
+
152
+ const creds: StoredCredential = JSON.parse(keyStore as string)
153
+
154
+ if (creds.isDefault) {
155
+ logger.info(`alias ${alias} is set as default, removing default ...`)
156
+ await keychain.deletePassword(DEFAULT_ALIAS)
157
+ }
158
+ await keychain.deletePassword(alias)
159
+ logger.info(`Successfully removed credentials for alias ${alias}`)
160
+ }
161
+
162
+ export async function listCredentials(alias: string): Promise<void> {
163
+ if (process.env['NODE_ENV'] === 'test') {
164
+ return
165
+ }
166
+
167
+ const storedCreds = await fetchCredentials(alias)
168
+
169
+ if (storedCreds.size === 0) {
170
+ return
171
+ }
172
+
173
+ if (alias === 'all') {
174
+ logger.info(`Listing all credentials: `)
175
+
176
+ storedCreds.forEach((creds, alias) => {
177
+ prettyPrintCredentials(creds, alias)
178
+ })
179
+ return
180
+ }
181
+
182
+ logger.info(`Listing credentials for alias ${alias} ...`)
183
+ prettyPrintCredentials(storedCreds.get(alias) as CredentialPreview)
184
+ }
185
+
186
+ function prettyPrintCredentials(storedCreds: CredentialPreview, alias?: string): void {
187
+ const { host, username, isDefault } = storedCreds
188
+ if (alias) {
189
+ console.log(chalk.cyan.bold(`[${alias}]`))
190
+ }
191
+ console.log(` host = ${host}`)
192
+ console.log(` username = ${username}`)
193
+ console.log(` ${isDefault ? chalk.green('default = Yes') : 'default = No'}`)
194
+ }
195
+
196
+ async function fetchCredentials(alias: string): Promise<Map<string, CredentialPreview>> {
197
+ const storedCreds: Map<string, CredentialPreview> = new Map()
198
+ if (alias === 'all') {
199
+ const credentials = await keychain.findCredentials()
200
+ if (!credentials || credentials.length === 0) {
201
+ logger.info(`No credentials found`)
202
+ return storedCreds
203
+ }
204
+
205
+ for (const credential of credentials) {
206
+ if (credential.account === DEFAULT_ALIAS) {
207
+ continue
208
+ }
209
+ const {
210
+ alias: storedAlias,
211
+ host,
212
+ username,
213
+ isDefault,
214
+ } = JSON.parse(credential.password as string) as StoredCredential
215
+ storedCreds.set(storedAlias, { host, username, isDefault })
216
+ }
217
+ return storedCreds
218
+ }
219
+
220
+ const keyStore = await keychain.getPassword(alias)
221
+
222
+ if (!keyStore) {
223
+ logger.info(`No credentials found for alias: ${alias}`)
224
+ return storedCreds
225
+ }
226
+
227
+ const { alias: storedAlias, host, username, isDefault } = JSON.parse(keyStore as string) as StoredCredential
228
+ storedCreds.set(storedAlias, { host, username, isDefault })
229
+
230
+ return storedCreds
231
+ }
232
+
233
+ function getOrigin(host?: string) {
234
+ if (!host) {
235
+ return ''
236
+ }
237
+ return new URL(host).origin
238
+ }
@@ -0,0 +1,23 @@
1
+ export class KeyChain {
2
+ constructor(private readonly service: string) {}
3
+
4
+ private async getSingleton() {
5
+ return (await import('keytar')).default
6
+ }
7
+
8
+ async getPassword(account: string): Promise<string | null> {
9
+ return this.getSingleton().then((k) => k.getPassword(this.service, account))
10
+ }
11
+
12
+ async setPassword(account: string, password: string): Promise<void> {
13
+ return this.getSingleton().then((k) => k.setPassword(this.service, account, password))
14
+ }
15
+
16
+ async deletePassword(account: string): Promise<boolean> {
17
+ return this.getSingleton().then((k) => k.deletePassword(this.service, account))
18
+ }
19
+
20
+ async findCredentials(): Promise<Array<{ account: string; password: string }>> {
21
+ return this.getSingleton().then((k) => k.findCredentials(this.service))
22
+ }
23
+ }
@@ -0,0 +1,21 @@
1
+ import { CommandModule, Argv, ArgumentsCamelCase } from 'yargs'
2
+ import { removeCredentials } from '../../../auth'
3
+
4
+ interface Arguments {
5
+ alias: string
6
+ }
7
+
8
+ export const clear: CommandModule<unknown, Arguments> = {
9
+ command: 'clear [alias]',
10
+ describe: 'Clear authentication credentials for an instance',
11
+ builder: async (yargs: Argv) => {
12
+ return yargs.positional('alias', {
13
+ describe: 'credential alias to clear',
14
+ type: 'string',
15
+ default: 'all',
16
+ })
17
+ },
18
+ handler: async function (args: ArgumentsCamelCase<Arguments>): Promise<void> {
19
+ await removeCredentials(args.alias)
20
+ },
21
+ }
@@ -0,0 +1,21 @@
1
+ import { CommandModule, Argv, ArgumentsCamelCase } from 'yargs'
2
+ import { listCredentials } from '../../../auth'
3
+
4
+ interface Arguments {
5
+ alias: string
6
+ }
7
+
8
+ export const list: CommandModule<unknown, Arguments> = {
9
+ command: 'list [alias]',
10
+ describe: 'List all available authentication credentials',
11
+ builder: async (yargs: Argv) => {
12
+ return yargs.positional('alias', {
13
+ describe: 'credential alias to view',
14
+ type: 'string',
15
+ default: 'all',
16
+ })
17
+ },
18
+ handler: async function (args: ArgumentsCamelCase<Arguments>): Promise<void> {
19
+ await listCredentials(args.alias)
20
+ },
21
+ }
@@ -0,0 +1,100 @@
1
+ import { CommandModule, Argv, ArgumentsCamelCase } from 'yargs'
2
+ import { storeCredentials } from '../../../auth'
3
+ import { input, password as passwordInput } from '@inquirer/prompts'
4
+ export const DEFAULT_HOST = 'http://localhost:8080'
5
+
6
+ interface Arguments {
7
+ host: string | undefined
8
+ username: string | undefined
9
+ alias: string
10
+ default: boolean
11
+ }
12
+ type Options = {
13
+ [K in keyof Arguments]: {
14
+ describe: string
15
+ defaultValue?: string
16
+ }
17
+ }
18
+
19
+ const options: Options = {
20
+ host: {
21
+ describe: 'Target host for application deployment',
22
+ defaultValue: DEFAULT_HOST,
23
+ },
24
+ username: {
25
+ describe: 'The username to authenticate with the instance',
26
+ defaultValue: 'admin',
27
+ },
28
+ alias: {
29
+ describe: 'The alias to use for the host and username combination',
30
+ },
31
+ default: {
32
+ describe: 'Set the alias as the default',
33
+ },
34
+ }
35
+
36
+ export const save: CommandModule<unknown, Arguments> = {
37
+ command: 'save <alias>',
38
+ describe: 'Store authentication credentials for an instance',
39
+ builder: async (yargs: Argv) => {
40
+ return yargs
41
+ .positional('alias', {
42
+ describe: options.alias.describe,
43
+ type: 'string',
44
+ demandOption: true,
45
+ })
46
+ .option('host', {
47
+ describe: options.host.describe,
48
+ type: 'string',
49
+ })
50
+ .option('username', {
51
+ describe: options.username.describe,
52
+ type: 'string',
53
+ })
54
+ .option('default', {
55
+ describe: options.default.describe,
56
+ type: 'boolean',
57
+ default: false,
58
+ alias: 'd',
59
+ })
60
+ .epilogue(`You will be prompted for a password to authenticate with the instance.`)
61
+ },
62
+ handler: async function (args: ArgumentsCamelCase<Arguments>): Promise<void> {
63
+ const { login: loginService } = await import('@servicenow/sdk-cli-core/dist/command/login/index.js')
64
+ const { logger } = await import('@servicenow/sdk-cli-core/dist/cli-util/logger/index.js')
65
+ try {
66
+ const host =
67
+ args.host ||
68
+ (await input({
69
+ message: options.host.describe,
70
+ default: options.host.defaultValue,
71
+ }))
72
+ logger.info(`Authenticating to instance "${host}".`)
73
+ const username =
74
+ args.username ||
75
+ (await input({
76
+ message: options.username.describe,
77
+ default: options.username.defaultValue,
78
+ }))
79
+ const password = await passwordInput({
80
+ message: 'The password to authenticate with the instance',
81
+ validate(val) {
82
+ return val.length > 0
83
+ },
84
+ })
85
+ const session = await loginService({ host, username, password })
86
+
87
+ if (!session) {
88
+ return
89
+ }
90
+
91
+ const { instanceUrl } = session
92
+ logger.successful(`Successfully authenticated to instance ${instanceUrl}.`)
93
+ logger.info(`Storing credentials for instance "${instanceUrl}" with alias ${args.alias}.`)
94
+ await storeCredentials(args.alias, instanceUrl, username, password, args.default)
95
+ logger.successful(`Successfully stored credentials for instance "${instanceUrl}" with alias ${args.alias}.`)
96
+ } catch (error) {
97
+ logger.error(error instanceof Error ? error.message : (error as string), error)
98
+ }
99
+ },
100
+ }
@@ -0,0 +1,21 @@
1
+ import { CommandModule, Argv, ArgumentsCamelCase } from 'yargs'
2
+ import { updateDefaultCredential } from '../../../auth'
3
+
4
+ interface Arguments {
5
+ alias: string
6
+ }
7
+
8
+ export const setDefault: CommandModule<unknown, Arguments> = {
9
+ command: 'set-default <alias>',
10
+ describe: 'Set/Update the default credential alias',
11
+ builder: async (yargs: Argv) => {
12
+ return yargs.positional('alias', {
13
+ describe: 'credential alias to set as default option',
14
+ type: 'string',
15
+ demandOption: true,
16
+ })
17
+ },
18
+ handler: async function (args: ArgumentsCamelCase<Arguments>): Promise<void> {
19
+ await updateDefaultCredential(args.alias)
20
+ },
21
+ }
@@ -0,0 +1,35 @@
1
+ import { CommandModule, Argv, ArgumentsCamelCase } from 'yargs'
2
+ import { getCredentials } from '../../../auth'
3
+
4
+ interface Arguments {
5
+ alias: string
6
+ }
7
+
8
+ export const validate: CommandModule<unknown, Arguments> = {
9
+ describe: 'Validate authentication credentials for an instance',
10
+ builder: async (yargs: Argv) => {
11
+ return yargs.positional('alias', {
12
+ describe: 'credential alias to validate against the instance',
13
+ type: 'string',
14
+ demandOption: true,
15
+ })
16
+ },
17
+ handler: async function (args: ArgumentsCamelCase<Arguments>): Promise<void> {
18
+ const { login: loginService } = await import('@servicenow/sdk-cli-core/dist/command/login/index.js')
19
+ const { logger } = await import('@servicenow/sdk-cli-core/dist/cli-util/logger/index.js')
20
+ try {
21
+ args['auth'] = args.alias //getCredentials expects alias from args.auth
22
+ const creds = await getCredentials(args)
23
+
24
+ const session = await loginService(creds)
25
+
26
+ if (!session) {
27
+ return
28
+ }
29
+ const { instanceUrl } = session
30
+ logger.successful(`Successfully validated creds with instance ${instanceUrl}.`)
31
+ } catch (error) {
32
+ logger.error(error instanceof Error ? error.message : (error as string), error)
33
+ }
34
+ },
35
+ }
@@ -0,0 +1,24 @@
1
+ import { Argv, CommandModule } from 'yargs'
2
+ import { save } from './commands/save'
3
+ import { clear } from './commands/clear'
4
+ import { setDefault } from './commands/setDefault'
5
+ import { list } from './commands/list'
6
+ import { validate } from './commands/validate'
7
+
8
+ export const auth: CommandModule<unknown, any> = {
9
+ command: 'auth <command>',
10
+ describe: 'Configure authentication to instance',
11
+ builder: (yargs: Argv) => {
12
+ return yargs
13
+ .command(save)
14
+ .command(clear)
15
+ .command(setDefault)
16
+ .command(list)
17
+ .command('validate <alias>', false, validate)
18
+ .demandCommand(1)
19
+ .epilogue('Use $now-sdk auth <command> --help for more information on subcommands.')
20
+ },
21
+ handler: async () => {
22
+ // do nothing
23
+ },
24
+ }
@@ -0,0 +1,96 @@
1
+ import { Argv, ArgumentsCamelCase, CommandModule } from 'yargs'
2
+ import path from 'node:path'
3
+ import { cwd } from '../../util'
4
+
5
+ interface Arguments {
6
+ source: string
7
+ debug: boolean
8
+ 'generate-deletes': boolean
9
+ lint: boolean
10
+ optimize: boolean
11
+ experimental: boolean
12
+ }
13
+
14
+ export const build: CommandModule<unknown, Arguments> = {
15
+ command: 'build [source]',
16
+ describe: 'Compile sources into app files and generate deployable package',
17
+ builder: (yargs: Argv) => {
18
+ return yargs
19
+ .positional('source', {
20
+ describe: `Path to "package.json"`,
21
+ default: cwd(),
22
+ type: 'string',
23
+ })
24
+ .option('debug', {
25
+ describe: 'Print debug output',
26
+ alias: 'd',
27
+ default: false,
28
+ type: 'boolean',
29
+ })
30
+ .option('generate-deletes', {
31
+ describe: 'Generate DELETE record updates for files removed between builds',
32
+ default: true,
33
+ type: 'boolean',
34
+ })
35
+ .option('lint', {
36
+ describe: 'Lint sources before building',
37
+ default: true,
38
+ type: 'boolean',
39
+ })
40
+ .option('optimize', {
41
+ describe: 'Optimize packaging by reusing unchanged dependency xmls',
42
+ default: true,
43
+ type: 'boolean',
44
+ alias: 'o',
45
+ })
46
+ .option('experimental', {
47
+ describe: 'Enables unstable experimental feature that may or may not be supported long term',
48
+ default: false,
49
+ type: 'boolean',
50
+ alias: 'e',
51
+ hidden: true,
52
+ })
53
+ },
54
+ handler: async function (args: ArgumentsCamelCase<Arguments>): Promise<void> {
55
+ const { logger } = await import('@servicenow/sdk-cli-core/dist/cli-util/logger/index.js')
56
+ logger.info('Initiating the build process...')
57
+
58
+ const { clean } = await import('@servicenow/sdk-cli-core/dist/command/clean/index.js')
59
+ const { pack } = await import('@servicenow/sdk-cli-core/dist/command/pack/index.js')
60
+ const { generateModules } = await import('@servicenow/sdk-cli-core/dist/command/generate-modules/index.js')
61
+ const { packageDependencies } = await import(
62
+ '@servicenow/sdk-cli-core/dist/command/package-dependencies/index.js'
63
+ )
64
+ const { compile } = await import('@servicenow/sdk-cli-core/dist/command/compile/index.js')
65
+ const { markFilesForDeployment, getFilesExcludedForDeployment } = await import(
66
+ '@servicenow/sdk-cli-core/dist/cli-util/DeployUtils.js'
67
+ )
68
+ const { moveDependencyXmls } = await import('@servicenow/sdk-cli-core/dist/cli-util/ModuleUtils.js')
69
+ try {
70
+ const workingDir = path.resolve(args.source)
71
+ const generateDeletes = args['generate-deletes']
72
+ const enableExperimental = args.experimental
73
+ await clean(workingDir)
74
+ const dependencies = await packageDependencies(workingDir, generateDeletes, args.optimize)
75
+ await generateModules(workingDir, generateDeletes, dependencies)
76
+ if (enableExperimental) {
77
+ await compile(workingDir, args.debug)
78
+ }
79
+ markFilesForDeployment(args.source)
80
+ await pack(workingDir, getFilesExcludedForDeployment(args.source))
81
+ moveDependencyXmls(workingDir)
82
+ writeMetrics(workingDir)
83
+ } catch (error) {
84
+ logger.error(error instanceof Error ? error.stack ?? error.message : (error as string), error)
85
+ }
86
+ },
87
+ }
88
+
89
+ async function writeMetrics(workingDir: string) {
90
+ const { writeCMDTimingMetric, writeCommandCountMetric } = await import(
91
+ '@servicenow/sdk-cli-core/dist/usage/Metrics.js'
92
+ )
93
+
94
+ writeCMDTimingMetric(['first_build_to_deploy_time', 'last_build_to_deploy_time'], workingDir)
95
+ writeCommandCountMetric('build_count', workingDir)
96
+ }
@@ -0,0 +1,22 @@
1
+ import { Argv, ArgumentsCamelCase, CommandModule } from 'yargs'
2
+ import path from 'node:path'
3
+ import { cwd } from '../../util'
4
+
5
+ interface Arguments {
6
+ source: string
7
+ }
8
+
9
+ export const clean: CommandModule<unknown, Arguments> = {
10
+ describe: 'Clean output directory',
11
+ builder: (yargs: Argv) => {
12
+ return yargs.positional('source', {
13
+ describe: `Path to "package.json"`,
14
+ default: cwd(),
15
+ type: 'string',
16
+ })
17
+ },
18
+ handler: async function (args: ArgumentsCamelCase<Arguments>): Promise<void> {
19
+ const { clean: cleanService } = await import('@servicenow/sdk-cli-core/dist/command/clean/index.js')
20
+ await cleanService(path.resolve(args.source))
21
+ },
22
+ }
@@ -0,0 +1,31 @@
1
+ import { Argv, ArgumentsCamelCase, CommandModule } from 'yargs'
2
+ import path from 'node:path'
3
+ import { cwd } from '../../util'
4
+
5
+ interface Arguments {
6
+ source: string
7
+ experimental: boolean
8
+ }
9
+
10
+ export const compile: CommandModule<unknown, Arguments> = {
11
+ describe: 'Generate metadata files',
12
+ builder: (yargs: Argv) => {
13
+ return yargs
14
+ .positional('source', {
15
+ describe: `Path to "package.json"`,
16
+ default: cwd(),
17
+ type: 'string',
18
+ })
19
+ .option('experimental', {
20
+ describe: 'Enables unstable experimental feature that may or may not be supported long term',
21
+ default: false,
22
+ type: 'boolean',
23
+ alias: 'e',
24
+ hidden: true,
25
+ })
26
+ },
27
+ handler: async function (args: ArgumentsCamelCase<Arguments>): Promise<void> {
28
+ const { compile: compileService } = await import('@servicenow/sdk-cli-core/dist/command/compile/index.js')
29
+ await compileService(path.resolve(args.source))
30
+ },
31
+ }