@uipath/admin-tool 1.203.0-preview.205 → 1.204.0-preview.206

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.
@@ -0,0 +1,2375 @@
1
+ import {
2
+ ExternalApiResourceApi,
3
+ ExternalClientApi,
4
+ GroupApi,
5
+ ReferenceTokenApi,
6
+ RobotAccountApi,
7
+ SettingApi,
8
+ UserApi,
9
+ createApiClient,
10
+ createIdentityConfig
11
+ } from "./tool-mhb6cezm.js";
12
+ import"./tool-016jy57n.js";
13
+ import {
14
+ DEFAULT_PAGE_SIZE,
15
+ Option,
16
+ OutputFormatter,
17
+ RESULTS,
18
+ catchError,
19
+ extractErrorMessage,
20
+ logger,
21
+ processContext,
22
+ splitScopeList
23
+ } from "./tool-v13kh7v7.js";
24
+ import"./tool-1yh8g550.js";
25
+
26
+ // ../identity-commands/src/commands/external-apps.ts
27
+ var INSTRUCTIONS = {
28
+ list: "Verify you are logged in. Run 'external-apps list --help' for options.",
29
+ get: "Verify the app ID exists. Use 'external-apps list' to find valid IDs.",
30
+ create: "Verify scopes are correct. Provide --user-scope and/or --app-scope.",
31
+ update: "Verify the app ID is correct.",
32
+ delete: "Verify the app ID exists. The app may have already been deleted.",
33
+ generateSecret: "Verify the app ID is correct.",
34
+ deleteSecret: "Verify the secret ID exists. Use 'external-apps get' to find valid secret IDs.",
35
+ fedCredList: "Verify the client ID is correct.",
36
+ fedCredGet: "Verify the credential ID exists. Use 'federated-credentials list' to find valid IDs.",
37
+ fedCredCreate: "Provide --name, --issuer, --audience, and --subject. These must match the external identity provider.",
38
+ fedCredUpdate: "Verify the credential ID exists and provide the updated fields.",
39
+ fedCredDelete: "Verify the credential ID exists. It may have already been deleted."
40
+ };
41
+ var EXTERNAL_APPS_LIST_EXAMPLES = [
42
+ {
43
+ Description: "List external apps in a partition",
44
+ Command: "uip admin external-apps list",
45
+ Output: {
46
+ Code: "ExternalClientList",
47
+ Data: [
48
+ {
49
+ id: "my-app",
50
+ name: "My Application",
51
+ isConfidential: true
52
+ }
53
+ ]
54
+ }
55
+ }
56
+ ];
57
+ var EXTERNAL_APPS_GET_EXAMPLES = [
58
+ {
59
+ Description: "Get external app details",
60
+ Command: "uip admin external-apps get my-app",
61
+ Output: {
62
+ Code: "ExternalClientDetails",
63
+ Data: {
64
+ id: "my-app",
65
+ name: "My Application",
66
+ isConfidential: true,
67
+ redirectUri: "https://example.com/callback"
68
+ }
69
+ }
70
+ }
71
+ ];
72
+ var EXTERNAL_APPS_CREATE_EXAMPLES = [
73
+ {
74
+ Description: "Create a confidential app with application scopes",
75
+ Command: 'uip admin external-apps create "My App" --app-scope "OR.Folders,OR.Assets"',
76
+ Output: {
77
+ Code: "ExternalClientCreated",
78
+ Data: {
79
+ id: "my-app",
80
+ name: "My App",
81
+ isConfidential: true,
82
+ secret: "generated-secret-value"
83
+ }
84
+ }
85
+ },
86
+ {
87
+ Description: "Create a confidential app with both user and application scopes",
88
+ Command: 'uip admin external-apps create "My App" --user-scope "OR.Folders" --app-scope "OR.Jobs" --redirect-uri "https://example.com/callback"',
89
+ Output: {
90
+ Code: "ExternalClientCreated",
91
+ Data: {
92
+ id: "my-app",
93
+ name: "My App",
94
+ isConfidential: true,
95
+ secret: "generated-secret-value"
96
+ }
97
+ }
98
+ },
99
+ {
100
+ Description: "Create a non-confidential app with user scopes",
101
+ Command: 'uip admin external-apps create "My SPA" --non-confidential --user-scope "OR.Folders" --redirect-uri "http://localhost:3000/callback"',
102
+ Output: {
103
+ Code: "ExternalClientCreated",
104
+ Data: {
105
+ id: "my-spa",
106
+ name: "My SPA",
107
+ isConfidential: false
108
+ }
109
+ }
110
+ }
111
+ ];
112
+ var EXTERNAL_APPS_GENERATE_SECRET_EXAMPLES = [
113
+ {
114
+ Description: "Generate a new secret for an external app",
115
+ Command: "uip admin external-apps generate-secret my-app",
116
+ Output: {
117
+ Code: "ExternalClientSecretGenerated",
118
+ Data: {
119
+ id: 1,
120
+ secret: "generated-secret-value"
121
+ }
122
+ }
123
+ }
124
+ ];
125
+ var EXTERNAL_APPS_UPDATE_EXAMPLES = [
126
+ {
127
+ Description: "Update app name and scopes",
128
+ Command: 'uip admin external-apps update my-app-id --name "Updated App" --app-scope "OR.Folders"',
129
+ Output: {
130
+ Code: "ExternalClientUpdated"
131
+ }
132
+ }
133
+ ];
134
+ var EXTERNAL_APPS_DELETE_EXAMPLES = [
135
+ {
136
+ Description: "Delete an external app",
137
+ Command: "uip admin external-apps delete my-app-id",
138
+ Output: {
139
+ Code: "ExternalClientDeleted",
140
+ Data: { Id: "my-app-id", Status: "Deleted successfully" }
141
+ }
142
+ }
143
+ ];
144
+ var EXTERNAL_APPS_DELETE_SECRET_EXAMPLES = [
145
+ {
146
+ Description: "Delete a secret from an external app",
147
+ Command: "uip admin external-apps delete-secret 12345",
148
+ Output: {
149
+ Code: "ExternalClientSecretDeleted",
150
+ Data: { Id: "12345", Status: "Deleted successfully" }
151
+ }
152
+ }
153
+ ];
154
+ var FED_CRED_LIST_EXAMPLES = [
155
+ {
156
+ Description: "List federated credentials for an external app",
157
+ Command: "uip admin external-apps federated-credentials list my-app-id",
158
+ Output: {
159
+ Code: "FederatedCredentialList",
160
+ Data: [
161
+ {
162
+ id: "fc000000-0000-0000-0000-000000000001",
163
+ name: "GitHub Actions",
164
+ issuer: "https://token.actions.githubusercontent.com"
165
+ }
166
+ ]
167
+ }
168
+ }
169
+ ];
170
+ var FED_CRED_GET_EXAMPLES = [
171
+ {
172
+ Description: "Get a federated credential by ID",
173
+ Command: "uip admin external-apps federated-credentials get my-app-id fc000000-0000-0000-0000-000000000001",
174
+ Output: {
175
+ Code: "FederatedCredentialDetails",
176
+ Data: {
177
+ id: "fc000000-0000-0000-0000-000000000001",
178
+ name: "GitHub Actions",
179
+ issuer: "https://token.actions.githubusercontent.com",
180
+ audience: "api://AzureADTokenExchange",
181
+ subject: "repo:org/repo:ref:refs/heads/main"
182
+ }
183
+ }
184
+ }
185
+ ];
186
+ var FED_CRED_CREATE_EXAMPLES = [
187
+ {
188
+ Description: "Create a federated credential for GitHub Actions OIDC",
189
+ Command: 'uip admin external-apps federated-credentials create my-app-id --name "GitHub Actions" --issuer "https://token.actions.githubusercontent.com" --audience "api://AzureADTokenExchange" --subject "repo:org/repo:ref:refs/heads/main"',
190
+ Output: {
191
+ Code: "FederatedCredentialCreated"
192
+ }
193
+ }
194
+ ];
195
+ var FED_CRED_UPDATE_EXAMPLES = [
196
+ {
197
+ Description: "Update a federated credential",
198
+ Command: 'uip admin external-apps federated-credentials update my-app-id fc000000-0000-0000-0000-000000000001 --name "GitHub Actions (prod)" --issuer "https://token.actions.githubusercontent.com" --audience "api://AzureADTokenExchange" --subject "repo:org/repo:environment:production"',
199
+ Output: {
200
+ Code: "FederatedCredentialUpdated"
201
+ }
202
+ }
203
+ ];
204
+ var FED_CRED_DELETE_EXAMPLES = [
205
+ {
206
+ Description: "Delete a federated credential",
207
+ Command: "uip admin external-apps federated-credentials delete my-app-id fc000000-0000-0000-0000-000000000001",
208
+ Output: {
209
+ Code: "FederatedCredentialDeleted",
210
+ Data: {
211
+ Id: "fc000000-0000-0000-0000-000000000001",
212
+ Status: "Deleted successfully"
213
+ }
214
+ }
215
+ }
216
+ ];
217
+ function parseScopes(list, type) {
218
+ return splitScopeList(list).map((name) => ({ name, type }));
219
+ }
220
+ function foldDeprecatedScopeAlias(options) {
221
+ if (options.scope !== undefined && options.appScope === undefined) {
222
+ options.appScope = options.scope;
223
+ return "--scope";
224
+ }
225
+ return "--app-scope";
226
+ }
227
+ function findBlankScopeOption(options, appScopeOption) {
228
+ if (options.userScope !== undefined && splitScopeList(options.userScope).length === 0) {
229
+ return "--user-scope";
230
+ }
231
+ if (options.appScope !== undefined && splitScopeList(options.appScope).length === 0) {
232
+ return appScopeOption;
233
+ }
234
+ return;
235
+ }
236
+ function reportBlankScopeOption(option) {
237
+ OutputFormatter.error({
238
+ Result: RESULTS.Failure,
239
+ Message: `No scope names found in ${option}.`,
240
+ Instructions: `Pass one or more scopes, comma- or space-separated (e.g. ${option} "OR.Folders,OR.Assets").`
241
+ });
242
+ processContext.exit(1);
243
+ }
244
+ function warnDeprecatedOrganization(org) {
245
+ if (org !== undefined) {
246
+ logger.warn("--organization is deprecated and ignored; organization is derived from login context");
247
+ }
248
+ }
249
+ var registerExternalAppsCommand = (program) => {
250
+ const externalApps = program.command("external-apps").description("Manage external OAuth2 clients. List, get, create, update, delete clients and manage secrets.");
251
+ externalApps.command("list").description("List external apps in a partition.").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(EXTERNAL_APPS_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
252
+ warnDeprecatedOrganization(options.organization);
253
+ const [error, result] = await catchError((async () => {
254
+ const { api, organizationId } = await createApiClient(ExternalClientApi, {
255
+ loginValidity: options.loginValidity,
256
+ organization: options.organization
257
+ });
258
+ const orgId = organizationId;
259
+ return await api.externalClientGet({
260
+ partitionGlobalId: orgId
261
+ });
262
+ })());
263
+ if (error) {
264
+ OutputFormatter.error({
265
+ Result: RESULTS.Failure,
266
+ Message: await extractErrorMessage(error),
267
+ Instructions: INSTRUCTIONS.list
268
+ });
269
+ processContext.exit(1);
270
+ return;
271
+ }
272
+ OutputFormatter.success({
273
+ Result: RESULTS.Success,
274
+ Code: "ExternalClientList",
275
+ Data: result ?? []
276
+ });
277
+ });
278
+ externalApps.command("get").description("Get external app details. " + "Use 'external-apps list' to retrieve the client ID.").argument("<client-id>", "External app ID").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(EXTERNAL_APPS_GET_EXAMPLES).trackedAction(processContext, async (clientId, options) => {
279
+ warnDeprecatedOrganization(options.organization);
280
+ const [error, client] = await catchError((async () => {
281
+ const { api, organizationId } = await createApiClient(ExternalClientApi, {
282
+ loginValidity: options.loginValidity,
283
+ organization: options.organization
284
+ });
285
+ const orgId = organizationId;
286
+ return await api.externalClientGetWithClientId({
287
+ partitionGlobalId: orgId,
288
+ clientId
289
+ });
290
+ })());
291
+ if (error) {
292
+ OutputFormatter.error({
293
+ Result: RESULTS.Failure,
294
+ Message: await extractErrorMessage(error),
295
+ Instructions: INSTRUCTIONS.get
296
+ });
297
+ processContext.exit(1);
298
+ return;
299
+ }
300
+ OutputFormatter.success({
301
+ Result: RESULTS.Success,
302
+ Code: "ExternalClientDetails",
303
+ Data: client
304
+ });
305
+ });
306
+ externalApps.command("create").description("Create an external app (confidential by default). " + "Use --non-confidential for public clients (SPAs, mobile apps).").argument("<name>", "App display name").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--redirect-uri <uri>", "Redirect URI(s) for OAuth2 flow (comma-separated for multiple)").option("--user-scope <scopes>", "User (delegated) scopes, comma- or space-separated").option("--app-scope <scopes>", "Application (app-only) scopes, comma- or space-separated").option("--scope <scopes>", "Alias for --app-scope (deprecated)").option("--non-confidential", "Create a non-confidential (public) app — no client secret, requires redirect URI").option("--no-secret", "Skip generating a client secret on creation").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(EXTERNAL_APPS_CREATE_EXAMPLES).trackedAction(processContext, async (name, options) => {
307
+ warnDeprecatedOrganization(options.organization);
308
+ const appScopeOption = foldDeprecatedScopeAlias(options);
309
+ const blankOption = findBlankScopeOption(options, appScopeOption);
310
+ if (blankOption) {
311
+ reportBlankScopeOption(blankOption);
312
+ return;
313
+ }
314
+ if (!options.userScope && !options.appScope) {
315
+ OutputFormatter.error({
316
+ Result: RESULTS.Failure,
317
+ Message: "At least one of --user-scope or --app-scope is required.",
318
+ Instructions: "Use --user-scope for delegated permissions and/or --app-scope for app-only permissions."
319
+ });
320
+ processContext.exit(1);
321
+ return;
322
+ }
323
+ const isConfidential = !options.nonConfidential;
324
+ const hasUserScopes = !!options.userScope;
325
+ if (!isConfidential && options.appScope) {
326
+ OutputFormatter.error({
327
+ Result: RESULTS.Failure,
328
+ Message: "Non-confidential apps only support user scopes. Use --user-scope instead of --app-scope.",
329
+ Instructions: "Remove --app-scope and use --user-scope for delegated permissions."
330
+ });
331
+ processContext.exit(1);
332
+ return;
333
+ }
334
+ if (!options.redirectUri && (!isConfidential || hasUserScopes)) {
335
+ const reason = !isConfidential ? "Non-confidential apps require" : "User scopes require";
336
+ OutputFormatter.error({
337
+ Result: RESULTS.Failure,
338
+ Message: `${reason} --redirect-uri for the OAuth2 authorization code flow.`,
339
+ Instructions: "Provide --redirect-uri (e.g. http://localhost:3000/callback)."
340
+ });
341
+ processContext.exit(1);
342
+ return;
343
+ }
344
+ const scopes = [
345
+ ...parseScopes(options.userScope, "user"),
346
+ ...parseScopes(options.appScope, "application")
347
+ ];
348
+ const generateFirstSecret = isConfidential && options.secret !== false;
349
+ const [error, result] = await catchError((async () => {
350
+ const { api, organizationId } = await createApiClient(ExternalClientApi, {
351
+ loginValidity: options.loginValidity,
352
+ organization: options.organization
353
+ });
354
+ const orgId = organizationId;
355
+ const createCommand = {
356
+ partitionGlobalId: orgId,
357
+ name,
358
+ isConfidential,
359
+ scopes,
360
+ redirectUri: options.redirectUri,
361
+ generateFirstSecret
362
+ };
363
+ return await api.externalClientCreate({
364
+ createExternalClientCommand: createCommand
365
+ });
366
+ })());
367
+ if (error) {
368
+ OutputFormatter.error({
369
+ Result: RESULTS.Failure,
370
+ Message: await extractErrorMessage(error),
371
+ Instructions: INSTRUCTIONS.create
372
+ });
373
+ processContext.exit(1);
374
+ return;
375
+ }
376
+ OutputFormatter.success({
377
+ Result: RESULTS.Success,
378
+ Code: "ExternalClientCreated",
379
+ Data: result
380
+ });
381
+ });
382
+ externalApps.command("update").description("Update an external app. Use 'external-apps list' to retrieve the client ID.").argument("<client-id>", "External app ID").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("-n, --name <name>", "New display name").option("--redirect-uri <uri>", "Redirect URI(s) for OAuth2 flow (comma-separated for multiple)").option("--user-scope <scopes>", "User (delegated) scopes, comma- or space-separated").option("--app-scope <scopes>", "Application (app-only) scopes, comma- or space-separated").option("--scope <scopes>", "Alias for --app-scope (deprecated)").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(EXTERNAL_APPS_UPDATE_EXAMPLES).trackedAction(processContext, async (clientId, options) => {
383
+ warnDeprecatedOrganization(options.organization);
384
+ const appScopeOption = foldDeprecatedScopeAlias(options);
385
+ const hasScopes = options.userScope !== undefined || options.appScope !== undefined;
386
+ if (options.name === undefined && options.redirectUri === undefined && !hasScopes) {
387
+ OutputFormatter.error({
388
+ Result: RESULTS.Failure,
389
+ Message: "No fields to update",
390
+ Instructions: "Provide at least one of --name, --redirect-uri, --user-scope, or --app-scope."
391
+ });
392
+ processContext.exit(1);
393
+ return;
394
+ }
395
+ const blankOption = findBlankScopeOption(options, appScopeOption);
396
+ if (blankOption) {
397
+ reportBlankScopeOption(blankOption);
398
+ return;
399
+ }
400
+ const [fetchError, fetchResult] = await catchError((async () => {
401
+ const { api: api2, organizationId } = await createApiClient(ExternalClientApi, {
402
+ loginValidity: options.loginValidity,
403
+ organization: options.organization
404
+ });
405
+ const orgId2 = organizationId;
406
+ const current2 = await api2.externalClientGetWithClientId({
407
+ partitionGlobalId: orgId2,
408
+ clientId
409
+ });
410
+ return { api: api2, orgId: orgId2, current: current2 };
411
+ })());
412
+ if (fetchError) {
413
+ OutputFormatter.error({
414
+ Result: RESULTS.Failure,
415
+ Message: await extractErrorMessage(fetchError),
416
+ Instructions: INSTRUCTIONS.update
417
+ });
418
+ processContext.exit(1);
419
+ return;
420
+ }
421
+ const { api, orgId, current } = fetchResult;
422
+ if (!current.isConfidential && options.appScope) {
423
+ OutputFormatter.error({
424
+ Result: RESULTS.Failure,
425
+ Message: "Non-confidential apps only support user scopes. Use --user-scope instead of --app-scope.",
426
+ Instructions: "Remove --app-scope and use --user-scope for delegated permissions."
427
+ });
428
+ processContext.exit(1);
429
+ return;
430
+ }
431
+ const hasUserScopes = options.userScope !== undefined;
432
+ const effectiveRedirectUri = options.redirectUri ?? current.redirectUri;
433
+ if (hasUserScopes && !effectiveRedirectUri) {
434
+ OutputFormatter.error({
435
+ Result: RESULTS.Failure,
436
+ Message: "User scopes require a redirect URI. Provide --redirect-uri or set one first.",
437
+ Instructions: "Provide --redirect-uri (e.g. http://localhost:3000/callback)."
438
+ });
439
+ processContext.exit(1);
440
+ return;
441
+ }
442
+ const scopes = hasScopes ? [
443
+ ...parseScopes(options.userScope, "user"),
444
+ ...parseScopes(options.appScope, "application")
445
+ ] : current.resources?.flatMap((r) => r.scopes ?? []) ?? [];
446
+ const updateCommand = {
447
+ scopes
448
+ };
449
+ if (options.name !== undefined)
450
+ updateCommand.name = options.name;
451
+ if (options.redirectUri !== undefined)
452
+ updateCommand.redirectUri = options.redirectUri;
453
+ const [error, result] = await catchError(api.externalClientUpdate({
454
+ partitionGlobalId: orgId,
455
+ clientId,
456
+ updateExternalClientCommand: updateCommand
457
+ }));
458
+ if (error) {
459
+ OutputFormatter.error({
460
+ Result: RESULTS.Failure,
461
+ Message: await extractErrorMessage(error),
462
+ Instructions: INSTRUCTIONS.update
463
+ });
464
+ processContext.exit(1);
465
+ return;
466
+ }
467
+ OutputFormatter.success({
468
+ Result: RESULTS.Success,
469
+ Code: "ExternalClientUpdated",
470
+ Data: result
471
+ });
472
+ });
473
+ externalApps.command("delete").description("Delete an external app. " + "Use 'external-apps list' to retrieve the client ID.").argument("<client-id>", "External app ID").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(EXTERNAL_APPS_DELETE_EXAMPLES).trackedAction(processContext, async (clientId, options) => {
474
+ warnDeprecatedOrganization(options.organization);
475
+ const [error] = await catchError((async () => {
476
+ const { api, organizationId } = await createApiClient(ExternalClientApi, {
477
+ loginValidity: options.loginValidity,
478
+ organization: options.organization
479
+ });
480
+ const orgId = organizationId;
481
+ return await api.externalClientDelete({
482
+ partitionGlobalId: orgId,
483
+ clientId
484
+ });
485
+ })());
486
+ if (error) {
487
+ OutputFormatter.error({
488
+ Result: RESULTS.Failure,
489
+ Message: await extractErrorMessage(error),
490
+ Instructions: INSTRUCTIONS.delete
491
+ });
492
+ processContext.exit(1);
493
+ return;
494
+ }
495
+ OutputFormatter.success({
496
+ Result: RESULTS.Success,
497
+ Code: "ExternalClientDeleted",
498
+ Data: {
499
+ Id: clientId,
500
+ Status: "Deleted successfully"
501
+ }
502
+ });
503
+ });
504
+ externalApps.command("generate-secret").description("Generate a new secret for an external app. " + "Returns the secret value (only shown once).").argument("<client-id>", "External app ID").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--description <text>", "Description for the secret").option("--expiration <date>", "Expiration date (ISO 8601)").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(EXTERNAL_APPS_GENERATE_SECRET_EXAMPLES).trackedAction(processContext, async (clientId, options) => {
505
+ warnDeprecatedOrganization(options.organization);
506
+ const [error, result] = await catchError((async () => {
507
+ const { api, organizationId } = await createApiClient(ExternalClientApi, {
508
+ loginValidity: options.loginValidity,
509
+ organization: options.organization
510
+ });
511
+ const orgId = organizationId;
512
+ return await api.externalClientGenerateSecret({
513
+ createClientSecretCommand: {
514
+ clientId,
515
+ partitionGlobalId: orgId,
516
+ description: options.description,
517
+ expiryTime: options.expiration ? new Date(options.expiration) : undefined
518
+ }
519
+ });
520
+ })());
521
+ if (error) {
522
+ OutputFormatter.error({
523
+ Result: RESULTS.Failure,
524
+ Message: await extractErrorMessage(error),
525
+ Instructions: INSTRUCTIONS.generateSecret
526
+ });
527
+ processContext.exit(1);
528
+ return;
529
+ }
530
+ OutputFormatter.success({
531
+ Result: RESULTS.Success,
532
+ Code: "ExternalClientSecretGenerated",
533
+ Data: result
534
+ });
535
+ });
536
+ externalApps.command("delete-secret").description("Delete a specific secret from an external app.").argument("<secret-id>", "Secret ID (numeric)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(EXTERNAL_APPS_DELETE_SECRET_EXAMPLES).trackedAction(processContext, async (secretId, options) => {
537
+ warnDeprecatedOrganization(options.organization);
538
+ const [error] = await catchError((async () => {
539
+ const { api, organizationId } = await createApiClient(ExternalClientApi, {
540
+ loginValidity: options.loginValidity,
541
+ organization: options.organization
542
+ });
543
+ const orgId = organizationId;
544
+ return await api.externalClientDeleteSecret({
545
+ partitionGlobalId: orgId,
546
+ secretId: Number.parseInt(secretId, 10)
547
+ });
548
+ })());
549
+ if (error) {
550
+ OutputFormatter.error({
551
+ Result: RESULTS.Failure,
552
+ Message: await extractErrorMessage(error),
553
+ Instructions: INSTRUCTIONS.deleteSecret
554
+ });
555
+ processContext.exit(1);
556
+ return;
557
+ }
558
+ OutputFormatter.success({
559
+ Result: RESULTS.Success,
560
+ Code: "ExternalClientSecretDeleted",
561
+ Data: {
562
+ Id: secretId,
563
+ Status: "Deleted successfully"
564
+ }
565
+ });
566
+ });
567
+ const fedCreds = externalApps.command("federated-credentials").description("Manage federated credentials for external apps. " + "Enable workload identity federation with external identity providers (e.g. GitHub Actions, Azure AD).");
568
+ fedCreds.command("list").description("List federated credentials for an external app.").argument("<client-id>", "External app ID").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(FED_CRED_LIST_EXAMPLES).trackedAction(processContext, async (clientId, options) => {
569
+ warnDeprecatedOrganization(options.organization);
570
+ const [error, result] = await catchError((async () => {
571
+ const { api, organizationId } = await createApiClient(ExternalClientApi, {
572
+ loginValidity: options.loginValidity,
573
+ organization: options.organization
574
+ });
575
+ const orgId = organizationId;
576
+ return await api.externalClientGetFederatedCredentials({
577
+ partitionGlobalId: orgId,
578
+ clientId
579
+ });
580
+ })());
581
+ if (error) {
582
+ OutputFormatter.error({
583
+ Result: RESULTS.Failure,
584
+ Message: await extractErrorMessage(error),
585
+ Instructions: INSTRUCTIONS.fedCredList
586
+ });
587
+ processContext.exit(1);
588
+ return;
589
+ }
590
+ OutputFormatter.success({
591
+ Result: RESULTS.Success,
592
+ Code: "FederatedCredentialList",
593
+ Data: result ?? []
594
+ });
595
+ });
596
+ fedCreds.command("get").description("Get a federated credential by ID.").argument("<client-id>", "External app ID").argument("<credential-id>", "Federated credential ID (UUID)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(FED_CRED_GET_EXAMPLES).trackedAction(processContext, async (clientId, credentialId, options) => {
597
+ warnDeprecatedOrganization(options.organization);
598
+ const [error, result] = await catchError((async () => {
599
+ const { api, organizationId } = await createApiClient(ExternalClientApi, {
600
+ loginValidity: options.loginValidity,
601
+ organization: options.organization
602
+ });
603
+ const orgId = organizationId;
604
+ return await api.externalClientGetFederatedCredentialByIdByCredentialId({
605
+ partitionGlobalId: orgId,
606
+ clientId,
607
+ credentialId
608
+ });
609
+ })());
610
+ if (error) {
611
+ OutputFormatter.error({
612
+ Result: RESULTS.Failure,
613
+ Message: await extractErrorMessage(error),
614
+ Instructions: INSTRUCTIONS.fedCredGet
615
+ });
616
+ processContext.exit(1);
617
+ return;
618
+ }
619
+ OutputFormatter.success({
620
+ Result: RESULTS.Success,
621
+ Code: "FederatedCredentialDetails",
622
+ Data: result
623
+ });
624
+ });
625
+ fedCreds.command("create").description("Create a federated credential for an external app. " + "Maps an external identity (e.g. GitHub Actions OIDC) to this app.").argument("<client-id>", "External app ID").requiredOption("-n, --name <name>", "Credential name").requiredOption("--issuer <url>", "Token issuer URL (e.g. https://token.actions.githubusercontent.com)").requiredOption("--audience <audience>", "Expected audience claim (e.g. api://AzureADTokenExchange)").requiredOption("--subject <subject>", "Expected subject claim (e.g. repo:org/repo:ref:refs/heads/main)").option("--description <text>", "Description for the credential").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(FED_CRED_CREATE_EXAMPLES).trackedAction(processContext, async (clientId, options) => {
626
+ warnDeprecatedOrganization(options.organization);
627
+ const [error, result] = await catchError((async () => {
628
+ const { api, organizationId } = await createApiClient(ExternalClientApi, {
629
+ loginValidity: options.loginValidity,
630
+ organization: options.organization
631
+ });
632
+ const orgId = organizationId;
633
+ const cmd = {
634
+ name: options.name,
635
+ issuer: options.issuer,
636
+ audience: options.audience,
637
+ subject: options.subject,
638
+ description: options.description
639
+ };
640
+ return await api.externalClientCreateFederatedCredential({
641
+ partitionGlobalId: orgId,
642
+ clientId,
643
+ createFederatedCredentialCommand: cmd
644
+ });
645
+ })());
646
+ if (error) {
647
+ OutputFormatter.error({
648
+ Result: RESULTS.Failure,
649
+ Message: await extractErrorMessage(error),
650
+ Instructions: INSTRUCTIONS.fedCredCreate
651
+ });
652
+ processContext.exit(1);
653
+ return;
654
+ }
655
+ OutputFormatter.success({
656
+ Result: RESULTS.Success,
657
+ Code: "FederatedCredentialCreated",
658
+ Data: result
659
+ });
660
+ });
661
+ fedCreds.command("update").description("Update a federated credential.").argument("<client-id>", "External app ID").argument("<credential-id>", "Federated credential ID (UUID)").requiredOption("-n, --name <name>", "Credential name").requiredOption("--issuer <url>", "Token issuer URL").requiredOption("--audience <audience>", "Expected audience claim").requiredOption("--subject <subject>", "Expected subject claim").option("--description <text>", "Description for the credential").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(FED_CRED_UPDATE_EXAMPLES).trackedAction(processContext, async (clientId, credentialId, options) => {
662
+ warnDeprecatedOrganization(options.organization);
663
+ const [error, result] = await catchError((async () => {
664
+ const { api, organizationId } = await createApiClient(ExternalClientApi, {
665
+ loginValidity: options.loginValidity,
666
+ organization: options.organization
667
+ });
668
+ const orgId = organizationId;
669
+ const cmd = {
670
+ name: options.name,
671
+ issuer: options.issuer,
672
+ audience: options.audience,
673
+ subject: options.subject,
674
+ description: options.description
675
+ };
676
+ return await api.externalClientUpdateFederatedCredential({
677
+ partitionGlobalId: orgId,
678
+ clientId,
679
+ credentialId,
680
+ updateFederatedCredentialCommand: cmd
681
+ });
682
+ })());
683
+ if (error) {
684
+ OutputFormatter.error({
685
+ Result: RESULTS.Failure,
686
+ Message: await extractErrorMessage(error),
687
+ Instructions: INSTRUCTIONS.fedCredUpdate
688
+ });
689
+ processContext.exit(1);
690
+ return;
691
+ }
692
+ OutputFormatter.success({
693
+ Result: RESULTS.Success,
694
+ Code: "FederatedCredentialUpdated",
695
+ Data: result
696
+ });
697
+ });
698
+ fedCreds.command("delete").description("Delete a federated credential from an external app.").argument("<client-id>", "External app ID").argument("<credential-id>", "Federated credential ID (UUID)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(FED_CRED_DELETE_EXAMPLES).trackedAction(processContext, async (clientId, credentialId, options) => {
699
+ warnDeprecatedOrganization(options.organization);
700
+ const [error] = await catchError((async () => {
701
+ const { api, organizationId } = await createApiClient(ExternalClientApi, {
702
+ loginValidity: options.loginValidity,
703
+ organization: options.organization
704
+ });
705
+ const orgId = organizationId;
706
+ return await api.externalClientDeleteFederatedCredential({
707
+ partitionGlobalId: orgId,
708
+ clientId,
709
+ credentialId
710
+ });
711
+ })());
712
+ if (error) {
713
+ OutputFormatter.error({
714
+ Result: RESULTS.Failure,
715
+ Message: await extractErrorMessage(error),
716
+ Instructions: INSTRUCTIONS.fedCredDelete
717
+ });
718
+ processContext.exit(1);
719
+ return;
720
+ }
721
+ OutputFormatter.success({
722
+ Result: RESULTS.Success,
723
+ Code: "FederatedCredentialDeleted",
724
+ Data: {
725
+ Id: credentialId,
726
+ Status: "Deleted successfully"
727
+ }
728
+ });
729
+ });
730
+ };
731
+
732
+ // ../identity-commands/src/commands/groups.ts
733
+ var INSTRUCTIONS2 = {
734
+ list: "Verify you are logged in. Run 'groups list --help' for options.",
735
+ get: "Verify the group ID exists. Use 'groups list' to find valid IDs.",
736
+ create: "Verify the group name is correct. Group names must be unique within a partition.",
737
+ update: "Verify the group ID is correct. Use 'groups list' to find valid IDs.",
738
+ delete: "Verify the group ID exists. The group may have already been deleted.",
739
+ listMembers: "Verify the group ID is correct.",
740
+ addMembers: "Verify the group ID and user IDs are correct. Use 'users list' to find valid user IDs.",
741
+ revokeMembers: "Verify the user IDs are current members of the group."
742
+ };
743
+ var GROUPS_LIST_EXAMPLES = [
744
+ {
745
+ Description: "List groups in a partition",
746
+ Command: "uip admin groups list",
747
+ Output: {
748
+ Code: "GroupList",
749
+ Data: [
750
+ {
751
+ id: "a1b2c3d4-0000-0000-0000-000000000001",
752
+ name: "Administrators",
753
+ displayName: "Administrators",
754
+ type: "BuiltIn",
755
+ creationTime: "2026-01-15T10:00:00.000Z"
756
+ }
757
+ ]
758
+ }
759
+ }
760
+ ];
761
+ var GROUPS_GET_EXAMPLES = [
762
+ {
763
+ Description: "Get group details",
764
+ Command: "uip admin groups get a1b2c3d4-0000-0000-0000-000000000001",
765
+ Output: {
766
+ Code: "GroupDetails",
767
+ Data: {
768
+ id: "a1b2c3d4-0000-0000-0000-000000000001",
769
+ name: "Administrators",
770
+ displayName: "Administrators",
771
+ type: "BuiltIn",
772
+ creationTime: "2026-01-15T10:00:00.000Z"
773
+ }
774
+ }
775
+ }
776
+ ];
777
+ var GROUPS_CREATE_EXAMPLES = [
778
+ {
779
+ Description: "Create a new group",
780
+ Command: 'uip admin groups create "DevOps Team"',
781
+ Output: {
782
+ Code: "GroupCreated",
783
+ Data: {
784
+ id: "a1b2c3d4-0000-0000-0000-000000000002",
785
+ name: "DevOps Team",
786
+ displayName: "DevOps Team",
787
+ type: "Custom"
788
+ }
789
+ }
790
+ }
791
+ ];
792
+ var GROUPS_UPDATE_EXAMPLES = [
793
+ {
794
+ Description: "Rename a group",
795
+ Command: 'uip admin groups update a1b2c3d4-0000-0000-0000-000000000001 --name "Renamed Group"',
796
+ Output: {
797
+ Code: "GroupUpdated"
798
+ }
799
+ }
800
+ ];
801
+ var GROUPS_DELETE_EXAMPLES = [
802
+ {
803
+ Description: "Delete a group",
804
+ Command: "uip admin groups delete a1b2c3d4-0000-0000-0000-000000000002",
805
+ Output: {
806
+ Code: "GroupDeleted",
807
+ Data: {
808
+ Id: "a1b2c3d4-0000-0000-0000-000000000002",
809
+ Status: "Deleted successfully"
810
+ }
811
+ }
812
+ }
813
+ ];
814
+ var MEMBERS_LIST_EXAMPLES = [
815
+ {
816
+ Description: "List members of a group",
817
+ Command: "uip admin groups members list a1b2c3d4-0000-0000-0000-000000000001",
818
+ Output: {
819
+ Code: "GroupMembers"
820
+ }
821
+ }
822
+ ];
823
+ var MEMBERS_ADD_EXAMPLES = [
824
+ {
825
+ Description: "Add users to a group",
826
+ Command: 'uip admin groups members add a1b2c3d4-0000-0000-0000-000000000001 --user-ids "user-id-1,user-id-2"',
827
+ Output: {
828
+ Code: "GroupMembersAdded"
829
+ }
830
+ }
831
+ ];
832
+ var MEMBERS_REVOKE_EXAMPLES = [
833
+ {
834
+ Description: "Revoke users from a group",
835
+ Command: 'uip admin groups members revoke a1b2c3d4-0000-0000-0000-000000000001 --user-ids "user-id-1"',
836
+ Output: {
837
+ Code: "GroupMembersRevoked"
838
+ }
839
+ }
840
+ ];
841
+ function warnDeprecatedOrganization2(org) {
842
+ if (org !== undefined) {
843
+ logger.warn("--organization is deprecated and ignored; organization is derived from login context");
844
+ }
845
+ }
846
+ var registerGroupsCommand = (program) => {
847
+ const groups = program.command("groups").description("Manage groups. List, get, create, update, and delete groups within a partition.");
848
+ groups.command("list").description("List all groups in a partition. " + "Returns group ID, name, type, and creation time.").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(GROUPS_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
849
+ warnDeprecatedOrganization2(options.organization);
850
+ const [error, result] = await catchError((async () => {
851
+ const { api, organizationId } = await createApiClient(GroupApi, {
852
+ loginValidity: options.loginValidity
853
+ });
854
+ const orgId = organizationId;
855
+ return await api.groupGetGroups({
856
+ partitionGlobalId: orgId
857
+ });
858
+ })());
859
+ if (error) {
860
+ OutputFormatter.error({
861
+ Result: RESULTS.Failure,
862
+ Message: await extractErrorMessage(error),
863
+ Instructions: INSTRUCTIONS2.list
864
+ });
865
+ processContext.exit(1);
866
+ return;
867
+ }
868
+ OutputFormatter.success({
869
+ Result: RESULTS.Success,
870
+ Code: "GroupList",
871
+ Data: result ?? []
872
+ });
873
+ });
874
+ groups.command("get").description("Get group details by ID. " + "Use 'groups list' to retrieve the group ID.").argument("<group-id>", "Group ID (UUID)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(GROUPS_GET_EXAMPLES).trackedAction(processContext, async (groupId, options) => {
875
+ warnDeprecatedOrganization2(options.organization);
876
+ const [error, group] = await catchError((async () => {
877
+ const { api, organizationId } = await createApiClient(GroupApi, {
878
+ loginValidity: options.loginValidity
879
+ });
880
+ const orgId = organizationId;
881
+ return await api.groupGetGroup({
882
+ partitionGlobalId: orgId,
883
+ groupId
884
+ });
885
+ })());
886
+ if (error) {
887
+ OutputFormatter.error({
888
+ Result: RESULTS.Failure,
889
+ Message: await extractErrorMessage(error),
890
+ Instructions: INSTRUCTIONS2.get
891
+ });
892
+ processContext.exit(1);
893
+ return;
894
+ }
895
+ OutputFormatter.success({
896
+ Result: RESULTS.Success,
897
+ Code: "GroupDetails",
898
+ Data: group
899
+ });
900
+ });
901
+ groups.command("create").description("Create a new local group in a partition.").argument("<name>", "Group name").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(GROUPS_CREATE_EXAMPLES).trackedAction(processContext, async (name, options) => {
902
+ warnDeprecatedOrganization2(options.organization);
903
+ const [error, result] = await catchError((async () => {
904
+ const { api, organizationId } = await createApiClient(GroupApi, {
905
+ loginValidity: options.loginValidity
906
+ });
907
+ const orgId = organizationId;
908
+ const createCommand = {
909
+ id: crypto.randomUUID(),
910
+ name,
911
+ partitionGlobalId: orgId
912
+ };
913
+ return await api.groupCreateGroup({
914
+ createGroupCommand: createCommand
915
+ });
916
+ })());
917
+ if (error) {
918
+ OutputFormatter.error({
919
+ Result: RESULTS.Failure,
920
+ Message: await extractErrorMessage(error),
921
+ Instructions: INSTRUCTIONS2.create
922
+ });
923
+ processContext.exit(1);
924
+ return;
925
+ }
926
+ OutputFormatter.success({
927
+ Result: RESULTS.Success,
928
+ Code: "GroupCreated",
929
+ Data: result
930
+ });
931
+ });
932
+ groups.command("update").description("Update a group. Use 'groups list' to retrieve the group ID.").argument("<group-id>", "Group ID (UUID)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("-n, --name <name>", "New group name").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(GROUPS_UPDATE_EXAMPLES).trackedAction(processContext, async (groupId, options) => {
933
+ warnDeprecatedOrganization2(options.organization);
934
+ if (options.name === undefined) {
935
+ OutputFormatter.error({
936
+ Result: RESULTS.Failure,
937
+ Message: "No fields to update",
938
+ Instructions: "Provide --name to rename the group."
939
+ });
940
+ processContext.exit(1);
941
+ return;
942
+ }
943
+ const [error, result] = await catchError((async () => {
944
+ const { api, organizationId } = await createApiClient(GroupApi, {
945
+ loginValidity: options.loginValidity
946
+ });
947
+ const orgId = organizationId;
948
+ const updateCommand = {
949
+ partitionGlobalId: orgId,
950
+ name: options.name
951
+ };
952
+ return await api.groupUpdateGroup({
953
+ groupId,
954
+ updateGroupCommand: updateCommand
955
+ });
956
+ })());
957
+ if (error) {
958
+ OutputFormatter.error({
959
+ Result: RESULTS.Failure,
960
+ Message: await extractErrorMessage(error),
961
+ Instructions: INSTRUCTIONS2.update
962
+ });
963
+ processContext.exit(1);
964
+ return;
965
+ }
966
+ OutputFormatter.success({
967
+ Result: RESULTS.Success,
968
+ Code: "GroupUpdated",
969
+ Data: result
970
+ });
971
+ });
972
+ groups.command("delete").description("Delete a group. " + "Use 'groups list' to retrieve the group ID.").argument("<group-id>", "Group ID (UUID)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(GROUPS_DELETE_EXAMPLES).trackedAction(processContext, async (groupId, options) => {
973
+ warnDeprecatedOrganization2(options.organization);
974
+ const [error] = await catchError((async () => {
975
+ const { api, organizationId } = await createApiClient(GroupApi, {
976
+ loginValidity: options.loginValidity
977
+ });
978
+ const orgId = organizationId;
979
+ return await api.groupDelete({
980
+ partitionGlobalId: orgId,
981
+ groupId
982
+ });
983
+ })());
984
+ if (error) {
985
+ OutputFormatter.error({
986
+ Result: RESULTS.Failure,
987
+ Message: await extractErrorMessage(error),
988
+ Instructions: INSTRUCTIONS2.delete
989
+ });
990
+ processContext.exit(1);
991
+ return;
992
+ }
993
+ OutputFormatter.success({
994
+ Result: RESULTS.Success,
995
+ Code: "GroupDeleted",
996
+ Data: {
997
+ Id: groupId,
998
+ Status: "Deleted successfully"
999
+ }
1000
+ });
1001
+ });
1002
+ const members = groups.command("members").description("Manage group membership. List, add, or revoke members.");
1003
+ members.command("list").description("List members of a group. " + "Use 'groups list' to retrieve the group ID.").argument("<group-id>", "Group ID (UUID)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("-l, --limit <number>", "Number of items to return", "50").option("--offset <number>", "Number of items to skip", "0").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(MEMBERS_LIST_EXAMPLES).trackedAction(processContext, async (groupId, options) => {
1004
+ warnDeprecatedOrganization2(options.organization);
1005
+ const [error, result] = await catchError((async () => {
1006
+ const { api, organizationId } = await createApiClient(GroupApi, {
1007
+ loginValidity: options.loginValidity
1008
+ });
1009
+ const orgId = organizationId;
1010
+ return await api.groupGetGroupMembers({
1011
+ partitionGlobalId: orgId,
1012
+ groupId,
1013
+ top: Number.parseInt(options.limit, 10),
1014
+ skip: Number.parseInt(options.offset || "0", 10)
1015
+ });
1016
+ })());
1017
+ if (error) {
1018
+ OutputFormatter.error({
1019
+ Result: RESULTS.Failure,
1020
+ Message: await extractErrorMessage(error),
1021
+ Instructions: INSTRUCTIONS2.listMembers
1022
+ });
1023
+ processContext.exit(1);
1024
+ return;
1025
+ }
1026
+ OutputFormatter.success({
1027
+ Result: RESULTS.Success,
1028
+ Code: "GroupMembers",
1029
+ Data: result.results ?? []
1030
+ });
1031
+ });
1032
+ members.command("add").description("Add users to a group. Pass comma-separated user IDs.").argument("<group-id>", "Group ID (UUID)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").requiredOption("--user-ids <ids>", "Comma-separated user IDs to add").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(MEMBERS_ADD_EXAMPLES).trackedAction(processContext, async (groupId, options) => {
1033
+ warnDeprecatedOrganization2(options.organization);
1034
+ const userIds = options.userIds.split(",").map((id) => id.trim());
1035
+ const [error, result] = await catchError((async () => {
1036
+ const { api, organizationId } = await createApiClient(GroupApi, {
1037
+ loginValidity: options.loginValidity
1038
+ });
1039
+ const orgId = organizationId;
1040
+ const group = await api.groupGetGroup({
1041
+ partitionGlobalId: orgId,
1042
+ groupId
1043
+ });
1044
+ return await api.groupUpdateGroup({
1045
+ groupId,
1046
+ updateGroupCommand: {
1047
+ partitionGlobalId: orgId,
1048
+ name: group.name,
1049
+ directoryUserIDsToAdd: userIds
1050
+ }
1051
+ });
1052
+ })());
1053
+ if (error) {
1054
+ OutputFormatter.error({
1055
+ Result: RESULTS.Failure,
1056
+ Message: await extractErrorMessage(error),
1057
+ Instructions: INSTRUCTIONS2.addMembers
1058
+ });
1059
+ processContext.exit(1);
1060
+ return;
1061
+ }
1062
+ OutputFormatter.success({
1063
+ Result: RESULTS.Success,
1064
+ Code: "GroupMembersAdded",
1065
+ Data: result
1066
+ });
1067
+ });
1068
+ members.command("revoke").description("Revoke users from a group. Pass comma-separated user IDs.").argument("<group-id>", "Group ID (UUID)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").requiredOption("--user-ids <ids>", "Comma-separated user IDs to revoke").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(MEMBERS_REVOKE_EXAMPLES).trackedAction(processContext, async (groupId, options) => {
1069
+ warnDeprecatedOrganization2(options.organization);
1070
+ const userIds = options.userIds.split(",").map((id) => id.trim());
1071
+ const [error, result] = await catchError((async () => {
1072
+ const { api, organizationId } = await createApiClient(GroupApi, {
1073
+ loginValidity: options.loginValidity
1074
+ });
1075
+ const orgId = organizationId;
1076
+ const group = await api.groupGetGroup({
1077
+ partitionGlobalId: orgId,
1078
+ groupId
1079
+ });
1080
+ return await api.groupUpdateGroup({
1081
+ groupId,
1082
+ updateGroupCommand: {
1083
+ partitionGlobalId: orgId,
1084
+ name: group.name,
1085
+ directoryUserIDsToRemove: userIds
1086
+ }
1087
+ });
1088
+ })());
1089
+ if (error) {
1090
+ OutputFormatter.error({
1091
+ Result: RESULTS.Failure,
1092
+ Message: await extractErrorMessage(error),
1093
+ Instructions: INSTRUCTIONS2.revokeMembers
1094
+ });
1095
+ processContext.exit(1);
1096
+ return;
1097
+ }
1098
+ OutputFormatter.success({
1099
+ Result: RESULTS.Success,
1100
+ Code: "GroupMembersRevoked",
1101
+ Data: result
1102
+ });
1103
+ });
1104
+ };
1105
+
1106
+ // ../identity-commands/src/commands/pat.ts
1107
+ var ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
1108
+ function parseIsoDate(value) {
1109
+ if (!ISO_DATE_PATTERN.test(value))
1110
+ return null;
1111
+ const date = new Date(value);
1112
+ if (Number.isNaN(date.getTime()))
1113
+ return null;
1114
+ const [year, month, day] = value.split("-").map(Number);
1115
+ if (date.getUTCFullYear() !== year || date.getUTCMonth() + 1 !== month || date.getUTCDate() !== day) {
1116
+ return null;
1117
+ }
1118
+ return date;
1119
+ }
1120
+ function parsePaginationInt(value, _name) {
1121
+ const num = Number.parseInt(value, 10);
1122
+ if (Number.isNaN(num) || num < 0 || String(num) !== value)
1123
+ return null;
1124
+ return num;
1125
+ }
1126
+ var INSTRUCTIONS3 = {
1127
+ list: "Verify you are logged in to the correct organization. Run 'pat list --help' for options.",
1128
+ create: "Provide --description, --expiration, and --scope. Use 'pat list' to verify existing tokens.",
1129
+ revoke: "Verify the token ID exists. Use 'pat list' to find valid IDs.",
1130
+ regenerate: "Verify the token ID exists and provide a new --expiration date."
1131
+ };
1132
+ var PAT_LIST_EXAMPLES = [
1133
+ {
1134
+ Description: "List personal access tokens",
1135
+ Command: "uip admin pat list",
1136
+ Output: {
1137
+ Code: "PatList",
1138
+ Data: [
1139
+ {
1140
+ id: "a1b2c3d4-0000-0000-0000-000000000001",
1141
+ description: "CI/CD token",
1142
+ expiration: "2027-01-15T00:00:00.000Z",
1143
+ scopes: ["OR.Folders.Read"]
1144
+ }
1145
+ ]
1146
+ }
1147
+ }
1148
+ ];
1149
+ var PAT_CREATE_EXAMPLES = [
1150
+ {
1151
+ Description: "Create a personal access token",
1152
+ Command: 'uip admin pat create --description "CI/CD token" --expiration 2027-01-15 --scope "OR.Folders.Read,OR.Jobs.Read"',
1153
+ Output: {
1154
+ Code: "PatCreated"
1155
+ }
1156
+ }
1157
+ ];
1158
+ var PAT_REVOKE_EXAMPLES = [
1159
+ {
1160
+ Description: "Revoke a personal access token",
1161
+ Command: "uip admin pat revoke a1b2c3d4-0000-0000-0000-000000000001",
1162
+ Output: {
1163
+ Code: "PatRevoked"
1164
+ }
1165
+ }
1166
+ ];
1167
+ var PAT_REGENERATE_EXAMPLES = [
1168
+ {
1169
+ Description: "Regenerate a personal access token with a new expiration",
1170
+ Command: "uip admin pat regenerate a1b2c3d4-0000-0000-0000-000000000001 --expiration 2028-01-15",
1171
+ Output: {
1172
+ Code: "PatRegenerated"
1173
+ }
1174
+ }
1175
+ ];
1176
+ var registerPatCommand = (program) => {
1177
+ const pat = program.command("pat").description("Manage personal access tokens (PATs). " + "Create, list, revoke, and regenerate tokens for API authentication.");
1178
+ pat.command("list").description("List personal access tokens. " + "By default lists your own tokens. Use --scope all to list all tokens in the organization (requires admin).").option("--scope <scope>", 'Token scope: "all" lists all tokens in the org (admin), omit for current user only').option("--search <term>", "Filter tokens by user search term. Implies --scope all.", undefined).option("-l, --limit <number>", "Number of items to return", String(DEFAULT_PAGE_SIZE)).option("--offset <number>", "Number of items to skip", "0").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(PAT_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
1179
+ if (options.scope !== undefined && options.scope !== "all") {
1180
+ OutputFormatter.error({
1181
+ Result: RESULTS.Failure,
1182
+ Message: `Invalid scope: "${options.scope}". Only "all" is supported.`,
1183
+ Instructions: "Use --scope all to list all tokens in the organization, or omit for your own tokens."
1184
+ });
1185
+ processContext.exit(1);
1186
+ return;
1187
+ }
1188
+ const isAll = options.scope === "all" || options.search !== undefined;
1189
+ const top = parsePaginationInt(options.limit, "limit");
1190
+ const skip = parsePaginationInt(options.offset || "0", "offset");
1191
+ if (top === null || skip === null) {
1192
+ OutputFormatter.error({
1193
+ Result: RESULTS.Failure,
1194
+ Message: `Invalid pagination: --limit "${options.limit}", --offset "${options.offset || "0"}". Must be non-negative integers.`,
1195
+ Instructions: INSTRUCTIONS3.list
1196
+ });
1197
+ processContext.exit(1);
1198
+ return;
1199
+ }
1200
+ const [error, result] = await catchError((async () => {
1201
+ const { api, organizationId } = await createApiClient(ReferenceTokenApi, {
1202
+ loginValidity: options.loginValidity
1203
+ });
1204
+ if (isAll) {
1205
+ return await api.referenceTokenGetTokensForPartition({
1206
+ partitionGlobalId: organizationId,
1207
+ userSearchTerm: options.search,
1208
+ top,
1209
+ skip
1210
+ });
1211
+ }
1212
+ const tokens = await api.referenceTokenGetTokens();
1213
+ return { results: tokens.slice(skip, skip + top) };
1214
+ })());
1215
+ if (error) {
1216
+ OutputFormatter.error({
1217
+ Result: RESULTS.Failure,
1218
+ Message: await extractErrorMessage(error),
1219
+ Instructions: INSTRUCTIONS3.list
1220
+ });
1221
+ processContext.exit(1);
1222
+ return;
1223
+ }
1224
+ OutputFormatter.success({
1225
+ Result: RESULTS.Success,
1226
+ Code: "PatList",
1227
+ Data: result.results ?? []
1228
+ });
1229
+ });
1230
+ pat.command("create").description("Create a new personal access token. " + "Returns the token value (shown only once).").requiredOption("--description <text>", "Description for the token").requiredOption("--expiration <date>", "Expiration date (ISO 8601, e.g. 2027-01-15)").requiredOption("--scope <scopes>", "Comma-separated list of scopes (e.g. OR.Folders.Read,OR.Jobs.Read)").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(PAT_CREATE_EXAMPLES).trackedAction(processContext, async (options) => {
1231
+ const scopes = options.scope.split(",").map((s) => s.trim()).filter(Boolean);
1232
+ if (scopes.length === 0) {
1233
+ OutputFormatter.error({
1234
+ Result: RESULTS.Failure,
1235
+ Message: "No valid scopes provided.",
1236
+ Instructions: "Provide at least one scope (e.g. OR.Folders.Read)."
1237
+ });
1238
+ processContext.exit(1);
1239
+ return;
1240
+ }
1241
+ const expiration = parseIsoDate(options.expiration);
1242
+ if (expiration === null) {
1243
+ OutputFormatter.error({
1244
+ Result: RESULTS.Failure,
1245
+ Message: `Invalid expiration date: "${options.expiration}".`,
1246
+ Instructions: "Provide a date in YYYY-MM-DD format (e.g. 2027-01-15)."
1247
+ });
1248
+ processContext.exit(1);
1249
+ return;
1250
+ }
1251
+ const [error, result] = await catchError((async () => {
1252
+ const { api } = await createApiClient(ReferenceTokenApi, {
1253
+ loginValidity: options.loginValidity
1254
+ });
1255
+ return await api.referenceTokenCreateToken({
1256
+ createReferenceTokenCommand: {
1257
+ description: options.description,
1258
+ expiration,
1259
+ scopes
1260
+ }
1261
+ });
1262
+ })());
1263
+ if (error) {
1264
+ OutputFormatter.error({
1265
+ Result: RESULTS.Failure,
1266
+ Message: await extractErrorMessage(error),
1267
+ Instructions: INSTRUCTIONS3.create
1268
+ });
1269
+ processContext.exit(1);
1270
+ return;
1271
+ }
1272
+ OutputFormatter.success({
1273
+ Result: RESULTS.Success,
1274
+ Code: "PatCreated",
1275
+ Data: {
1276
+ Token: result,
1277
+ Warning: "Save this token now. It will not be shown again."
1278
+ }
1279
+ });
1280
+ });
1281
+ pat.command("revoke").description("Revoke a personal access token. " + "Use 'pat list' to retrieve the token ID.").argument("<id>", "Token ID (UUID)").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(PAT_REVOKE_EXAMPLES).trackedAction(processContext, async (tokenId, options) => {
1282
+ const [error] = await catchError((async () => {
1283
+ const { api } = await createApiClient(ReferenceTokenApi, {
1284
+ loginValidity: options.loginValidity
1285
+ });
1286
+ await api.referenceTokenDeleteToken({
1287
+ referenceTokenId: tokenId
1288
+ });
1289
+ })());
1290
+ if (error) {
1291
+ OutputFormatter.error({
1292
+ Result: RESULTS.Failure,
1293
+ Message: await extractErrorMessage(error),
1294
+ Instructions: INSTRUCTIONS3.revoke
1295
+ });
1296
+ processContext.exit(1);
1297
+ return;
1298
+ }
1299
+ OutputFormatter.success({
1300
+ Result: RESULTS.Success,
1301
+ Code: "PatRevoked",
1302
+ Data: {
1303
+ Id: tokenId,
1304
+ Status: "Revoked successfully"
1305
+ }
1306
+ });
1307
+ });
1308
+ pat.command("regenerate").description("Regenerate a personal access token with a new expiration. " + "Returns the new token value (shown only once).").argument("<id>", "Token ID (UUID)").requiredOption("--expiration <date>", "New expiration date (ISO 8601, e.g. 2028-01-15)").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(PAT_REGENERATE_EXAMPLES).trackedAction(processContext, async (tokenId, options) => {
1309
+ const expiration = parseIsoDate(options.expiration);
1310
+ if (expiration === null) {
1311
+ OutputFormatter.error({
1312
+ Result: RESULTS.Failure,
1313
+ Message: `Invalid expiration date: "${options.expiration}".`,
1314
+ Instructions: "Provide a date in YYYY-MM-DD format (e.g. 2028-01-15)."
1315
+ });
1316
+ processContext.exit(1);
1317
+ return;
1318
+ }
1319
+ const [error, result] = await catchError((async () => {
1320
+ const { api } = await createApiClient(ReferenceTokenApi, {
1321
+ loginValidity: options.loginValidity
1322
+ });
1323
+ return await api.referenceTokenRegenerateToken({
1324
+ referenceTokenId: tokenId,
1325
+ regenerateReferenceTokenCommand: {
1326
+ expiration
1327
+ }
1328
+ });
1329
+ })());
1330
+ if (error) {
1331
+ OutputFormatter.error({
1332
+ Result: RESULTS.Failure,
1333
+ Message: await extractErrorMessage(error),
1334
+ Instructions: INSTRUCTIONS3.regenerate
1335
+ });
1336
+ processContext.exit(1);
1337
+ return;
1338
+ }
1339
+ OutputFormatter.success({
1340
+ Result: RESULTS.Success,
1341
+ Code: "PatRegenerated",
1342
+ Data: {
1343
+ Id: tokenId,
1344
+ Token: result,
1345
+ Warning: "Save this token now. It will not be shown again."
1346
+ }
1347
+ });
1348
+ });
1349
+ };
1350
+
1351
+ // ../identity-commands/src/commands/robot-accounts.ts
1352
+ var INSTRUCTIONS4 = {
1353
+ list: "Verify you are logged in. Run 'robot-accounts list --help' for options.",
1354
+ get: "Verify the robot account ID exists. Use 'robot-accounts list' to find valid IDs.",
1355
+ create: "Verify the robot account name is correct. Names must be unique within a partition.",
1356
+ update: "Verify the robot account ID is correct.",
1357
+ delete: "Verify the robot account ID exists. The account may have already been deleted."
1358
+ };
1359
+ var ROBOT_ACCOUNTS_LIST_EXAMPLES = [
1360
+ {
1361
+ Description: "List robot accounts in a partition",
1362
+ Command: "uip admin robot-accounts list --limit 5",
1363
+ Output: {
1364
+ Code: "RobotAccountList",
1365
+ Data: [
1366
+ {
1367
+ id: "a1b2c3d4-0000-0000-0000-000000000001",
1368
+ name: "automation-bot",
1369
+ displayName: "Automation Bot",
1370
+ creationTime: "2026-01-15T10:00:00.000Z"
1371
+ }
1372
+ ]
1373
+ }
1374
+ }
1375
+ ];
1376
+ var ROBOT_ACCOUNTS_GET_EXAMPLES = [
1377
+ {
1378
+ Description: "Get robot account details",
1379
+ Command: "uip admin robot-accounts get a1b2c3d4-0000-0000-0000-000000000001",
1380
+ Output: {
1381
+ Code: "RobotAccountDetails",
1382
+ Data: {
1383
+ id: "a1b2c3d4-0000-0000-0000-000000000001",
1384
+ name: "automation-bot",
1385
+ displayName: "Automation Bot",
1386
+ creationTime: "2026-01-15T10:00:00.000Z",
1387
+ groupIds: []
1388
+ }
1389
+ }
1390
+ }
1391
+ ];
1392
+ var ROBOT_ACCOUNTS_CREATE_EXAMPLES = [
1393
+ {
1394
+ Description: "Create a robot account",
1395
+ Command: 'uip admin robot-accounts create "automation-bot" --display-name "Automation Bot"',
1396
+ Output: {
1397
+ Code: "RobotAccountCreated",
1398
+ Data: {
1399
+ id: "a1b2c3d4-0000-0000-0000-000000000002",
1400
+ name: "automation-bot",
1401
+ displayName: "Automation Bot"
1402
+ }
1403
+ }
1404
+ }
1405
+ ];
1406
+ var ROBOT_ACCOUNTS_UPDATE_EXAMPLES = [
1407
+ {
1408
+ Description: "Update robot account display name",
1409
+ Command: 'uip admin robot-accounts update a1b2c3d4-0000-0000-0000-000000000001 --display-name "Updated Bot"',
1410
+ Output: {
1411
+ Code: "RobotAccountUpdated"
1412
+ }
1413
+ }
1414
+ ];
1415
+ var ROBOT_ACCOUNTS_DELETE_EXAMPLES = [
1416
+ {
1417
+ Description: "Delete a robot account",
1418
+ Command: "uip admin robot-accounts delete a1b2c3d4-0000-0000-0000-000000000001",
1419
+ Output: {
1420
+ Code: "RobotAccountDeleted",
1421
+ Data: {
1422
+ Id: "a1b2c3d4-0000-0000-0000-000000000001",
1423
+ Status: "Deleted successfully"
1424
+ }
1425
+ }
1426
+ }
1427
+ ];
1428
+ function warnDeprecatedOrganization3(org) {
1429
+ if (org !== undefined) {
1430
+ logger.warn("--organization is deprecated and ignored; organization is derived from login context");
1431
+ }
1432
+ }
1433
+ var registerRobotAccountsCommand = (program) => {
1434
+ const robotAccounts = program.command("robot-accounts").description("Manage robot accounts. List, get, create, update, and delete robot accounts within a partition.");
1435
+ robotAccounts.command("list").description("List robot accounts in a partition. " + "Returns account ID, name, display name, and creation time.").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("-s, --search <term>", "Search by name").option("--sort-by <field>", "Sort results by field (e.g., 'Name')").addOption(new Option("--sort-order <direction>", "Sort direction (default: asc)").choices(["asc", "desc"])).option("-l, --limit <number>", "Number of items to return", String(DEFAULT_PAGE_SIZE)).option("--offset <number>", "Number of items to skip", "0").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(ROBOT_ACCOUNTS_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
1436
+ warnDeprecatedOrganization3(options.organization);
1437
+ const [error, result] = await catchError((async () => {
1438
+ const { api, organizationId } = await createApiClient(RobotAccountApi, {
1439
+ loginValidity: options.loginValidity
1440
+ });
1441
+ const orgId = organizationId;
1442
+ return await api.robotAccountGetRobotAccounts({
1443
+ partitionGlobalId: orgId,
1444
+ searchTerm: options.search,
1445
+ sortBy: options.sortBy,
1446
+ sortOrder: options.sortOrder,
1447
+ top: Number.parseInt(options.limit, 10),
1448
+ skip: Number.parseInt(options.offset || "0", 10)
1449
+ });
1450
+ })());
1451
+ if (error) {
1452
+ OutputFormatter.error({
1453
+ Result: RESULTS.Failure,
1454
+ Message: await extractErrorMessage(error),
1455
+ Instructions: INSTRUCTIONS4.list
1456
+ });
1457
+ processContext.exit(1);
1458
+ return;
1459
+ }
1460
+ OutputFormatter.success({
1461
+ Result: RESULTS.Success,
1462
+ Code: "RobotAccountList",
1463
+ Data: result.results ?? []
1464
+ });
1465
+ });
1466
+ robotAccounts.command("get").description("Get robot account details by ID. " + "Use 'robot-accounts list' to retrieve the ID.").argument("<robot-account-id>", "Robot account ID (UUID)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(ROBOT_ACCOUNTS_GET_EXAMPLES).trackedAction(processContext, async (robotAccountId, options) => {
1467
+ warnDeprecatedOrganization3(options.organization);
1468
+ const [error, account] = await catchError((async () => {
1469
+ const { api, organizationId } = await createApiClient(RobotAccountApi, {
1470
+ loginValidity: options.loginValidity
1471
+ });
1472
+ const orgId = organizationId;
1473
+ return await api.robotAccountGetRobotAccount({
1474
+ partitionGlobalId: orgId,
1475
+ robotAccountId
1476
+ });
1477
+ })());
1478
+ if (error) {
1479
+ OutputFormatter.error({
1480
+ Result: RESULTS.Failure,
1481
+ Message: await extractErrorMessage(error),
1482
+ Instructions: INSTRUCTIONS4.get
1483
+ });
1484
+ processContext.exit(1);
1485
+ return;
1486
+ }
1487
+ OutputFormatter.success({
1488
+ Result: RESULTS.Success,
1489
+ Code: "RobotAccountDetails",
1490
+ Data: account
1491
+ });
1492
+ });
1493
+ robotAccounts.command("create").description("Create a new robot account in a partition.").argument("<name>", "Robot account name").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--display-name <display-name>", "Display name").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(ROBOT_ACCOUNTS_CREATE_EXAMPLES).trackedAction(processContext, async (name, options) => {
1494
+ warnDeprecatedOrganization3(options.organization);
1495
+ const [error, result] = await catchError((async () => {
1496
+ const { api, organizationId } = await createApiClient(RobotAccountApi, {
1497
+ loginValidity: options.loginValidity
1498
+ });
1499
+ const orgId = organizationId;
1500
+ const createCommand = {
1501
+ name,
1502
+ displayName: options.displayName ?? name,
1503
+ partitionGlobalId: orgId
1504
+ };
1505
+ return await api.robotAccountCreateRobotAccount({
1506
+ createRobotAccountCommand: createCommand
1507
+ });
1508
+ })());
1509
+ if (error) {
1510
+ OutputFormatter.error({
1511
+ Result: RESULTS.Failure,
1512
+ Message: await extractErrorMessage(error),
1513
+ Instructions: INSTRUCTIONS4.create
1514
+ });
1515
+ processContext.exit(1);
1516
+ return;
1517
+ }
1518
+ OutputFormatter.success({
1519
+ Result: RESULTS.Success,
1520
+ Code: "RobotAccountCreated",
1521
+ Data: result
1522
+ });
1523
+ });
1524
+ robotAccounts.command("update").description("Update a robot account. Use 'robot-accounts list' to retrieve the ID.").argument("<robot-account-id>", "Robot account ID (UUID)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--display-name <display-name>", "New display name").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(ROBOT_ACCOUNTS_UPDATE_EXAMPLES).trackedAction(processContext, async (robotAccountId, options) => {
1525
+ warnDeprecatedOrganization3(options.organization);
1526
+ if (options.displayName === undefined) {
1527
+ OutputFormatter.error({
1528
+ Result: RESULTS.Failure,
1529
+ Message: "No fields to update",
1530
+ Instructions: "Provide --display-name to update the robot account."
1531
+ });
1532
+ processContext.exit(1);
1533
+ return;
1534
+ }
1535
+ const [error, result] = await catchError((async () => {
1536
+ const { api, organizationId } = await createApiClient(RobotAccountApi, {
1537
+ loginValidity: options.loginValidity
1538
+ });
1539
+ const orgId = organizationId;
1540
+ const updateCommand = {
1541
+ partitionGlobalId: orgId,
1542
+ displayName: options.displayName
1543
+ };
1544
+ return await api.robotAccountUpdateRobotAccount({
1545
+ robotAccountId,
1546
+ updateRobotAccountCommand: updateCommand
1547
+ });
1548
+ })());
1549
+ if (error) {
1550
+ OutputFormatter.error({
1551
+ Result: RESULTS.Failure,
1552
+ Message: await extractErrorMessage(error),
1553
+ Instructions: INSTRUCTIONS4.update
1554
+ });
1555
+ processContext.exit(1);
1556
+ return;
1557
+ }
1558
+ OutputFormatter.success({
1559
+ Result: RESULTS.Success,
1560
+ Code: "RobotAccountUpdated",
1561
+ Data: result
1562
+ });
1563
+ });
1564
+ robotAccounts.command("delete").description("Delete a robot account. " + "Use 'robot-accounts list' to retrieve the ID.").argument("<robot-account-id>", "Robot account ID (UUID)").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(ROBOT_ACCOUNTS_DELETE_EXAMPLES).trackedAction(processContext, async (robotAccountId, options) => {
1565
+ warnDeprecatedOrganization3(options.organization);
1566
+ const [error] = await catchError((async () => {
1567
+ const { api, organizationId } = await createApiClient(RobotAccountApi, {
1568
+ loginValidity: options.loginValidity
1569
+ });
1570
+ const orgId = organizationId;
1571
+ await api.robotAccountDelete({
1572
+ partitionGlobalId: orgId,
1573
+ robotAccountId
1574
+ });
1575
+ })());
1576
+ if (error) {
1577
+ OutputFormatter.error({
1578
+ Result: RESULTS.Failure,
1579
+ Message: await extractErrorMessage(error),
1580
+ Instructions: INSTRUCTIONS4.delete
1581
+ });
1582
+ processContext.exit(1);
1583
+ return;
1584
+ }
1585
+ OutputFormatter.success({
1586
+ Result: RESULTS.Success,
1587
+ Code: "RobotAccountDeleted",
1588
+ Data: {
1589
+ Id: robotAccountId,
1590
+ Status: "Deleted successfully"
1591
+ }
1592
+ });
1593
+ });
1594
+ };
1595
+
1596
+ // ../identity-commands/src/commands/scopes.ts
1597
+ var INSTRUCTIONS5 = {
1598
+ list: "Verify you are logged in. Run 'uip login status' to check."
1599
+ };
1600
+ var SCOPES_LIST_EXAMPLES = [
1601
+ {
1602
+ Description: "List available OAuth2 scopes",
1603
+ Command: "uip admin scopes list",
1604
+ Output: {
1605
+ Code: "ScopesList",
1606
+ Data: [
1607
+ {
1608
+ name: "UiPath.Orchestrator",
1609
+ displayName: "Orchestrator API Access",
1610
+ scopes: [
1611
+ {
1612
+ name: "OR.Folders",
1613
+ displayName: "OR.Folders",
1614
+ type: "user"
1615
+ }
1616
+ ]
1617
+ }
1618
+ ]
1619
+ }
1620
+ }
1621
+ ];
1622
+ var registerScopesCommand = (program) => {
1623
+ const scopes = program.command("scopes").description("Browse available OAuth2 scopes for external apps and personal access tokens.");
1624
+ scopes.command("list").description("List all available OAuth2 scopes grouped by resource.").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(SCOPES_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
1625
+ const [error, result] = await catchError((async () => {
1626
+ const { api } = await createApiClient(ExternalApiResourceApi, {
1627
+ loginValidity: options.loginValidity
1628
+ });
1629
+ return await api.externalApiResourceGet();
1630
+ })());
1631
+ if (error) {
1632
+ OutputFormatter.error({
1633
+ Result: RESULTS.Failure,
1634
+ Message: await extractErrorMessage(error),
1635
+ Instructions: INSTRUCTIONS5.list
1636
+ });
1637
+ processContext.exit(1);
1638
+ return;
1639
+ }
1640
+ OutputFormatter.success({
1641
+ Result: RESULTS.Success,
1642
+ Code: "ScopesList",
1643
+ Data: result ?? []
1644
+ });
1645
+ });
1646
+ };
1647
+
1648
+ // ../identity-commands/src/commands/smtp.ts
1649
+ var SMTP_SETTING_KEYS = [
1650
+ "Email.Smtp.Host",
1651
+ "Email.Smtp.Port",
1652
+ "Email.Smtp.UserName",
1653
+ "Email.Smtp.Password",
1654
+ "Email.Smtp.Domain",
1655
+ "Email.Smtp.EnableSsl",
1656
+ "Email.Smtp.UseDefaultCredentials",
1657
+ "Email.Smtp.FromEmail",
1658
+ "Email.Smtp.FromDisplayName",
1659
+ "Email.Smtp.ConnectionTimeout"
1660
+ ];
1661
+ var SMTP_SETTING_KEYS_READ = SMTP_SETTING_KEYS.filter((k) => k !== "Email.Smtp.Password");
1662
+ var INSTRUCTIONS6 = {
1663
+ get: "Verify you are logged in to the correct organization. Run 'smtp get --help' for options.",
1664
+ update: "Verify you are logged in and at least one SMTP field is provided.",
1665
+ delete: "Verify you are logged in. The settings may have already been deleted.",
1666
+ test: "Verify --recipient is a valid email address. Use 'smtp get' to check current settings."
1667
+ };
1668
+ function settingsToSmtpData(settings) {
1669
+ const data = {};
1670
+ for (const setting of settings) {
1671
+ switch (setting.key) {
1672
+ case "Email.Smtp.Host":
1673
+ data.host = setting.value ?? undefined;
1674
+ break;
1675
+ case "Email.Smtp.Port":
1676
+ data.port = setting.value ?? undefined;
1677
+ break;
1678
+ case "Email.Smtp.UserName":
1679
+ data.userName = setting.value ?? undefined;
1680
+ break;
1681
+ case "Email.Smtp.Domain":
1682
+ data.domain = setting.value ?? undefined;
1683
+ break;
1684
+ case "Email.Smtp.EnableSsl":
1685
+ data.enableSsl = setting.value ?? undefined;
1686
+ break;
1687
+ case "Email.Smtp.UseDefaultCredentials":
1688
+ data.useDefaultCredentials = setting.value ?? undefined;
1689
+ break;
1690
+ case "Email.Smtp.FromEmail":
1691
+ data.fromAddress = setting.value ?? undefined;
1692
+ break;
1693
+ case "Email.Smtp.FromDisplayName":
1694
+ data.fromDisplayName = setting.value ?? undefined;
1695
+ break;
1696
+ case "Email.Smtp.ConnectionTimeout":
1697
+ data.connectionTimeout = setting.value ?? undefined;
1698
+ break;
1699
+ }
1700
+ }
1701
+ return data;
1702
+ }
1703
+ function settingsToSmtpConfig(settings) {
1704
+ const config = {};
1705
+ for (const setting of settings) {
1706
+ const val = setting.value ?? undefined;
1707
+ switch (setting.key) {
1708
+ case "Email.Smtp.Host":
1709
+ config.host = val;
1710
+ break;
1711
+ case "Email.Smtp.Port":
1712
+ config.port = val ? Number.parseInt(val, 10) : undefined;
1713
+ break;
1714
+ case "Email.Smtp.UserName":
1715
+ config.userName = val;
1716
+ break;
1717
+ case "Email.Smtp.Password":
1718
+ config.password = val;
1719
+ break;
1720
+ case "Email.Smtp.Domain":
1721
+ config.domain = val;
1722
+ break;
1723
+ case "Email.Smtp.EnableSsl":
1724
+ config.enableSsl = val?.toLowerCase() === "true";
1725
+ break;
1726
+ case "Email.Smtp.UseDefaultCredentials":
1727
+ config.useDefaultCredentials = val?.toLowerCase() === "true";
1728
+ break;
1729
+ case "Email.Smtp.FromEmail":
1730
+ config.fromAddress = val;
1731
+ break;
1732
+ case "Email.Smtp.FromDisplayName":
1733
+ config.fromDisplayName = val;
1734
+ break;
1735
+ case "Email.Smtp.ConnectionTimeout":
1736
+ config.connectionTimeout = val ? Number.parseInt(val, 10) : undefined;
1737
+ break;
1738
+ }
1739
+ }
1740
+ return config;
1741
+ }
1742
+ function stripUndefined(obj) {
1743
+ const result = {};
1744
+ for (const [key, value] of Object.entries(obj)) {
1745
+ if (value !== undefined) {
1746
+ result[key] = value;
1747
+ }
1748
+ }
1749
+ return result;
1750
+ }
1751
+ function buildSettingsFromOptions(options) {
1752
+ const settings = [];
1753
+ if (options.host !== undefined) {
1754
+ settings.push({ key: "Email.Smtp.Host", value: options.host });
1755
+ }
1756
+ if (options.port !== undefined) {
1757
+ settings.push({ key: "Email.Smtp.Port", value: options.port });
1758
+ }
1759
+ if (options.username !== undefined) {
1760
+ settings.push({ key: "Email.Smtp.UserName", value: options.username });
1761
+ }
1762
+ if (options.password !== undefined) {
1763
+ settings.push({ key: "Email.Smtp.Password", value: options.password });
1764
+ }
1765
+ if (options.domain !== undefined) {
1766
+ settings.push({ key: "Email.Smtp.Domain", value: options.domain });
1767
+ }
1768
+ if (options.enableSsl !== undefined) {
1769
+ settings.push({
1770
+ key: "Email.Smtp.EnableSsl",
1771
+ value: options.enableSsl
1772
+ });
1773
+ }
1774
+ if (options.useDefaultCredentials !== undefined) {
1775
+ settings.push({
1776
+ key: "Email.Smtp.UseDefaultCredentials",
1777
+ value: options.useDefaultCredentials
1778
+ });
1779
+ }
1780
+ if (options.fromAddress !== undefined) {
1781
+ settings.push({
1782
+ key: "Email.Smtp.FromEmail",
1783
+ value: options.fromAddress
1784
+ });
1785
+ }
1786
+ if (options.fromDisplayName !== undefined) {
1787
+ settings.push({
1788
+ key: "Email.Smtp.FromDisplayName",
1789
+ value: options.fromDisplayName
1790
+ });
1791
+ }
1792
+ if (options.connectionTimeout !== undefined) {
1793
+ settings.push({
1794
+ key: "Email.Smtp.ConnectionTimeout",
1795
+ value: options.connectionTimeout
1796
+ });
1797
+ }
1798
+ return settings;
1799
+ }
1800
+ function buildSmtpConfig(options) {
1801
+ const hasAny = options.host !== undefined || options.port !== undefined || options.username !== undefined || options.password !== undefined || options.domain !== undefined || options.enableSsl !== undefined || options.useDefaultCredentials !== undefined || options.fromAddress !== undefined || options.fromDisplayName !== undefined || options.connectionTimeout !== undefined;
1802
+ if (!hasAny) {
1803
+ return;
1804
+ }
1805
+ return {
1806
+ host: options.host,
1807
+ port: options.port !== undefined ? Number.parseInt(options.port, 10) : undefined,
1808
+ userName: options.username,
1809
+ password: options.password,
1810
+ domain: options.domain,
1811
+ enableSsl: options.enableSsl !== undefined ? options.enableSsl === "true" : undefined,
1812
+ useDefaultCredentials: options.useDefaultCredentials !== undefined ? options.useDefaultCredentials === "true" : undefined,
1813
+ fromAddress: options.fromAddress,
1814
+ fromDisplayName: options.fromDisplayName,
1815
+ connectionTimeout: options.connectionTimeout !== undefined ? Number.parseInt(options.connectionTimeout, 10) : undefined
1816
+ };
1817
+ }
1818
+ var SMTP_GET_EXAMPLES = [
1819
+ {
1820
+ Description: "Get current SMTP settings",
1821
+ Command: "uip admin smtp get",
1822
+ Output: {
1823
+ Code: "SmtpSettings",
1824
+ Data: {
1825
+ host: "smtp.example.com",
1826
+ port: "587",
1827
+ userName: "noreply@example.com",
1828
+ enableSsl: "True",
1829
+ fromAddress: "noreply@example.com",
1830
+ fromDisplayName: "UiPath Platform"
1831
+ }
1832
+ }
1833
+ }
1834
+ ];
1835
+ var SMTP_UPDATE_EXAMPLES = [
1836
+ {
1837
+ Description: "Update SMTP host and port",
1838
+ Command: "uip admin smtp update --host smtp.example.com --port 587",
1839
+ Output: {
1840
+ Code: "SmtpSettingsUpdated"
1841
+ }
1842
+ },
1843
+ {
1844
+ Description: "Configure full SMTP settings",
1845
+ Command: "uip admin smtp update --host smtp.example.com --port 587 --username user@example.com --password secret --from-address noreply@example.com --enable-ssl true",
1846
+ Output: {
1847
+ Code: "SmtpSettingsUpdated"
1848
+ }
1849
+ }
1850
+ ];
1851
+ var SMTP_DELETE_EXAMPLES = [
1852
+ {
1853
+ Description: "Delete all SMTP settings",
1854
+ Command: "uip admin smtp delete",
1855
+ Output: {
1856
+ Code: "SmtpSettingsDeleted",
1857
+ Data: {
1858
+ Status: "Deleted successfully"
1859
+ }
1860
+ }
1861
+ }
1862
+ ];
1863
+ var SMTP_TEST_EXAMPLES = [
1864
+ {
1865
+ Description: "Test current SMTP settings by sending a test email",
1866
+ Command: "uip admin smtp test --recipient admin@example.com",
1867
+ Output: {
1868
+ Code: "SmtpTestSent",
1869
+ Data: {
1870
+ Recipient: "admin@example.com",
1871
+ Status: "Test email sent successfully"
1872
+ }
1873
+ }
1874
+ },
1875
+ {
1876
+ Description: "Test with custom SMTP settings without saving them",
1877
+ Command: "uip admin smtp test --recipient admin@example.com --host smtp.example.com --port 587 --username user@example.com --password secret",
1878
+ Output: {
1879
+ Code: "SmtpTestSent",
1880
+ Data: {
1881
+ Recipient: "admin@example.com",
1882
+ Status: "Test email sent successfully"
1883
+ }
1884
+ }
1885
+ }
1886
+ ];
1887
+ function parsePort(value) {
1888
+ const n = Number(value);
1889
+ if (!Number.isInteger(n) || n < 1 || n > 65535) {
1890
+ throw new Error("Port must be an integer between 1 and 65535.");
1891
+ }
1892
+ return String(n);
1893
+ }
1894
+ function parseTimeout(value) {
1895
+ const n = Number(value);
1896
+ if (!Number.isInteger(n) || n < 1 || n > 300000) {
1897
+ throw new Error("Connection timeout must be an integer between 1 and 300000.");
1898
+ }
1899
+ return String(n);
1900
+ }
1901
+ function addSmtpOptions(command) {
1902
+ return command.option("--host <host>", "SMTP server hostname").option("--port <port>", "SMTP server port", parsePort).option("--username <username>", "SMTP authentication username").option("--password <password>", "SMTP authentication password").option("--domain <domain>", "SMTP authentication domain").addOption(new Option("--enable-ssl <value>", "Enable SSL/TLS (true or false)").choices(["true", "false"])).addOption(new Option("--use-default-credentials <value>", "Use Windows default credentials (true or false)").choices(["true", "false"])).option("--from-address <email>", "Sender email address").option("--from-display-name <name>", "Sender display name").option("--connection-timeout <ms>", "Connection timeout in milliseconds (1-300000)", parseTimeout);
1903
+ }
1904
+ var registerSmtpCommand = (program) => {
1905
+ const smtp = program.command("smtp").description("Manage SMTP email settings. Get, update, delete, and test SMTP configuration.");
1906
+ smtp.command("get").description("Get current SMTP settings for the organization. " + "Returns host, port, sender address, SSL, and timeout configuration. " + "Password values are not returned.").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(SMTP_GET_EXAMPLES).trackedAction(processContext, async (options) => {
1907
+ const [error, result] = await catchError((async () => {
1908
+ const { api, organizationId } = await createApiClient(SettingApi, {
1909
+ loginValidity: options.loginValidity
1910
+ });
1911
+ const orgId = organizationId;
1912
+ return await api.settingGetSettingsBulk({
1913
+ key: SMTP_SETTING_KEYS_READ,
1914
+ partitionGlobalId: orgId
1915
+ });
1916
+ })());
1917
+ if (error) {
1918
+ OutputFormatter.error({
1919
+ Result: RESULTS.Failure,
1920
+ Message: await extractErrorMessage(error),
1921
+ Instructions: INSTRUCTIONS6.get
1922
+ });
1923
+ processContext.exit(1);
1924
+ return;
1925
+ }
1926
+ OutputFormatter.success({
1927
+ Result: RESULTS.Success,
1928
+ Code: "SmtpSettings",
1929
+ Data: settingsToSmtpData(result)
1930
+ });
1931
+ });
1932
+ const update = smtp.command("update").description("Update SMTP settings for the organization. " + "Only provided fields are updated; unspecified fields remain unchanged.").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10));
1933
+ addSmtpOptions(update).examples(SMTP_UPDATE_EXAMPLES).trackedAction(processContext, async (options) => {
1934
+ const userSettings = buildSettingsFromOptions(options);
1935
+ if (userSettings.length === 0) {
1936
+ OutputFormatter.error({
1937
+ Result: RESULTS.Failure,
1938
+ Message: "No SMTP fields to update",
1939
+ Instructions: "Provide at least one SMTP option (e.g. --host, --port). Run 'smtp update --help' for all options."
1940
+ });
1941
+ processContext.exit(1);
1942
+ return;
1943
+ }
1944
+ const [error, result] = await catchError((async () => {
1945
+ const { api, organizationId } = await createApiClient(SettingApi, {
1946
+ loginValidity: options.loginValidity
1947
+ });
1948
+ const orgId = organizationId;
1949
+ const existing = await api.settingGetSettingsBulk({
1950
+ key: SMTP_SETTING_KEYS_READ,
1951
+ partitionGlobalId: orgId
1952
+ });
1953
+ const merged = new Map;
1954
+ for (const s of existing) {
1955
+ if (s.key) {
1956
+ merged.set(s.key, s.value ?? null);
1957
+ }
1958
+ }
1959
+ for (const s of userSettings) {
1960
+ merged.set(s.key, s.value ?? null);
1961
+ }
1962
+ const settings = [...merged.entries()].map(([key, value]) => ({ key, value }));
1963
+ return await api.settingUpdateSettings({
1964
+ bulkCreateOrUpdateSettingsCommand: {
1965
+ settings,
1966
+ partitionGlobalId: orgId
1967
+ }
1968
+ });
1969
+ })());
1970
+ if (error) {
1971
+ OutputFormatter.error({
1972
+ Result: RESULTS.Failure,
1973
+ Message: await extractErrorMessage(error),
1974
+ Instructions: INSTRUCTIONS6.update
1975
+ });
1976
+ processContext.exit(1);
1977
+ return;
1978
+ }
1979
+ OutputFormatter.success({
1980
+ Result: RESULTS.Success,
1981
+ Code: "SmtpSettingsUpdated",
1982
+ Data: settingsToSmtpData(result)
1983
+ });
1984
+ });
1985
+ smtp.command("delete").description("Delete all SMTP settings for the organization. " + "This removes all email configuration.").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(SMTP_DELETE_EXAMPLES).trackedAction(processContext, async (options) => {
1986
+ const [error] = await catchError((async () => {
1987
+ const { api, organizationId } = await createApiClient(SettingApi, {
1988
+ loginValidity: options.loginValidity
1989
+ });
1990
+ const orgId = organizationId;
1991
+ return await api.settingBulkDelete({
1992
+ bulkDeleteSettingsCommand: {
1993
+ settings: SMTP_SETTING_KEYS,
1994
+ partitionGlobalId: orgId
1995
+ }
1996
+ });
1997
+ })());
1998
+ if (error) {
1999
+ OutputFormatter.error({
2000
+ Result: RESULTS.Failure,
2001
+ Message: await extractErrorMessage(error),
2002
+ Instructions: INSTRUCTIONS6.delete
2003
+ });
2004
+ processContext.exit(1);
2005
+ return;
2006
+ }
2007
+ OutputFormatter.success({
2008
+ Result: RESULTS.Success,
2009
+ Code: "SmtpSettingsDeleted",
2010
+ Data: {
2011
+ Status: "Deleted successfully"
2012
+ }
2013
+ });
2014
+ });
2015
+ const test = smtp.command("test").description("Test SMTP settings by sending a test email to a recipient. " + "Uses saved settings by default. " + "Pass SMTP options to test custom settings without saving them.").requiredOption("--recipient <email>", "Email address to send the test email to").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10));
2016
+ addSmtpOptions(test).examples(SMTP_TEST_EXAMPLES).trackedAction(processContext, async (options) => {
2017
+ const customConfig = buildSmtpConfig(options);
2018
+ if (customConfig !== undefined && options.password === undefined && options.useDefaultCredentials !== "true") {
2019
+ OutputFormatter.error({
2020
+ Result: RESULTS.Failure,
2021
+ Message: "The --password option is required when testing with custom SMTP settings (unless --use-default-credentials true)",
2022
+ Instructions: "Provide --password, --use-default-credentials true, or omit all SMTP options to test with saved settings."
2023
+ });
2024
+ processContext.exit(1);
2025
+ return;
2026
+ }
2027
+ const [error] = await catchError((async () => {
2028
+ const { api, organizationId } = await createApiClient(SettingApi, {
2029
+ loginValidity: options.loginValidity
2030
+ });
2031
+ let smtpSettings = customConfig;
2032
+ if (smtpSettings !== undefined) {
2033
+ const saved = await api.settingGetSettingsBulk({
2034
+ key: SMTP_SETTING_KEYS_READ,
2035
+ partitionGlobalId: organizationId
2036
+ });
2037
+ const base = settingsToSmtpConfig(saved);
2038
+ smtpSettings = {
2039
+ ...base,
2040
+ ...stripUndefined(smtpSettings)
2041
+ };
2042
+ }
2043
+ return await api.settingVerifySmtpSetting({
2044
+ verifySmtpSettingsCommand: {
2045
+ recipient: options.recipient,
2046
+ smtpSettings
2047
+ }
2048
+ });
2049
+ })());
2050
+ if (error) {
2051
+ OutputFormatter.error({
2052
+ Result: RESULTS.Failure,
2053
+ Message: await extractErrorMessage(error),
2054
+ Instructions: INSTRUCTIONS6.test
2055
+ });
2056
+ processContext.exit(1);
2057
+ return;
2058
+ }
2059
+ OutputFormatter.success({
2060
+ Result: RESULTS.Success,
2061
+ Code: "SmtpTestSent",
2062
+ Data: {
2063
+ Recipient: options.recipient,
2064
+ Status: "Test email sent successfully"
2065
+ }
2066
+ });
2067
+ });
2068
+ };
2069
+
2070
+ // ../identity-commands/src/commands/users.ts
2071
+ var INSTRUCTIONS7 = {
2072
+ list: "Verify you are logged in. Run 'users list --help' for options.",
2073
+ get: "Verify the user ID exists. Use 'users list' to find valid IDs.",
2074
+ create: "Verify --email is correct. The username may already exist.",
2075
+ update: "Verify the user ID exists. Use 'users list' to find valid IDs.",
2076
+ delete: "Verify the user ID exists. The user may have already been deleted.",
2077
+ invite: "Verify the email address is valid and the org allows invitations."
2078
+ };
2079
+ var USERS_LIST_EXAMPLES = [
2080
+ {
2081
+ Description: "List users in a partition",
2082
+ Command: "uip admin users list --limit 5",
2083
+ Output: {
2084
+ Code: "UserList",
2085
+ Data: [
2086
+ {
2087
+ id: "a1b2c3d4-0000-0000-0000-000000000001",
2088
+ userName: "admin@example.com",
2089
+ email: "admin@example.com",
2090
+ name: "Admin",
2091
+ surname: "User",
2092
+ displayName: "Admin User",
2093
+ creationTime: "2026-01-15T10:00:00.000Z"
2094
+ }
2095
+ ]
2096
+ }
2097
+ }
2098
+ ];
2099
+ var USERS_GET_EXAMPLES = [
2100
+ {
2101
+ Description: "Get user details by ID",
2102
+ Command: "uip admin users get a1b2c3d4-0000-0000-0000-000000000001",
2103
+ Output: {
2104
+ Code: "UserDetails",
2105
+ Data: {
2106
+ id: "a1b2c3d4-0000-0000-0000-000000000001",
2107
+ userName: "admin@example.com",
2108
+ email: "admin@example.com",
2109
+ name: "Admin",
2110
+ surname: "User",
2111
+ displayName: "Admin User",
2112
+ creationTime: "2026-01-15T10:00:00.000Z"
2113
+ }
2114
+ }
2115
+ }
2116
+ ];
2117
+ var USERS_CREATE_EXAMPLES = [
2118
+ {
2119
+ Description: "Create a new user",
2120
+ Command: 'uip admin users create newuser --email "user@example.com" --name "John" --surname "Doe"',
2121
+ Output: {
2122
+ Code: "UserCreated",
2123
+ Data: {
2124
+ Succeeded: true
2125
+ }
2126
+ }
2127
+ }
2128
+ ];
2129
+ var USERS_DELETE_EXAMPLES = [
2130
+ {
2131
+ Description: "Delete a user by ID",
2132
+ Command: "uip admin users delete a1b2c3d4-0000-0000-0000-000000000001",
2133
+ Output: {
2134
+ Code: "UserDeleted",
2135
+ Data: {
2136
+ Id: "a1b2c3d4-0000-0000-0000-000000000001",
2137
+ Status: "Deleted successfully"
2138
+ }
2139
+ }
2140
+ }
2141
+ ];
2142
+ var USERS_UPDATE_EXAMPLES = [
2143
+ {
2144
+ Description: "Update user name and email",
2145
+ Command: 'uip admin users update a1b2c3d4-0000-0000-0000-000000000001 --name "Jane" --surname "Doe" --email "jane@example.com"',
2146
+ Output: {
2147
+ Code: "UserUpdated"
2148
+ }
2149
+ }
2150
+ ];
2151
+ var USERS_INVITE_EXAMPLES = [
2152
+ {
2153
+ Description: "Invite a user by email",
2154
+ Command: 'uip admin users invite --email "user@example.com"',
2155
+ Output: {
2156
+ Code: "UsersInvited",
2157
+ Data: {
2158
+ succeeded: true
2159
+ }
2160
+ }
2161
+ }
2162
+ ];
2163
+ function warnDeprecatedOrganization4(org) {
2164
+ if (org !== undefined) {
2165
+ logger.warn("--organization is deprecated and ignored; organization is derived from login context");
2166
+ }
2167
+ }
2168
+ var registerUsersCommand = (program) => {
2169
+ const users = program.command("users").description("Manage users. List, get, create, update, and delete users.");
2170
+ users.command("list").description("List users in a partition. " + "Returns user ID, username, email, name, and creation time.").option("--organization <id>", "(deprecated, ignored) organization is derived from login").option("-s, --search <term>", "Search users by name or email").option("--sort-by <field>", "Sort results by field (e.g., 'UserName', 'Email')").addOption(new Option("--sort-order <direction>", "Sort direction (default: asc)").choices(["asc", "desc"])).option("-l, --limit <number>", "Number of items to return", String(DEFAULT_PAGE_SIZE)).option("--offset <number>", "Number of items to skip", "0").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(USERS_LIST_EXAMPLES).trackedAction(processContext, async (options) => {
2171
+ warnDeprecatedOrganization4(options.organization);
2172
+ const [error, result] = await catchError((async () => {
2173
+ const { api, organizationId } = await createApiClient(UserApi, {
2174
+ loginValidity: options.loginValidity
2175
+ });
2176
+ const orgId = organizationId;
2177
+ return await api.userGetUsers({
2178
+ partitionGlobalId: orgId,
2179
+ searchTerm: options.search,
2180
+ sortBy: options.sortBy,
2181
+ sortOrder: options.sortOrder,
2182
+ top: Number.parseInt(options.limit, 10),
2183
+ skip: Number.parseInt(options.offset || "0", 10)
2184
+ });
2185
+ })());
2186
+ if (error) {
2187
+ OutputFormatter.error({
2188
+ Result: RESULTS.Failure,
2189
+ Message: await extractErrorMessage(error),
2190
+ Instructions: INSTRUCTIONS7.list
2191
+ });
2192
+ processContext.exit(1);
2193
+ return;
2194
+ }
2195
+ OutputFormatter.success({
2196
+ Result: RESULTS.Success,
2197
+ Code: "UserList",
2198
+ Data: result.results ?? []
2199
+ });
2200
+ });
2201
+ users.command("get").description("Get user details by ID. Use 'users list' to retrieve the user ID.").argument("<user-id>", "User ID (UUID)").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(USERS_GET_EXAMPLES).trackedAction(processContext, async (userId, options) => {
2202
+ warnDeprecatedOrganization4(options.organization);
2203
+ const [error, user] = await catchError((async () => {
2204
+ const { api } = await createApiClient(UserApi, {
2205
+ loginValidity: options.loginValidity
2206
+ });
2207
+ return await api.userGetUser({ userId });
2208
+ })());
2209
+ if (error) {
2210
+ OutputFormatter.error({
2211
+ Result: RESULTS.Failure,
2212
+ Message: await extractErrorMessage(error),
2213
+ Instructions: INSTRUCTIONS7.get
2214
+ });
2215
+ processContext.exit(1);
2216
+ return;
2217
+ }
2218
+ OutputFormatter.success({
2219
+ Result: RESULTS.Success,
2220
+ Code: "UserDetails",
2221
+ Data: user
2222
+ });
2223
+ });
2224
+ users.command("create").description("Create a new user. Provide a username and email address.").argument("<username>", "Username for the new user").option("--organization <id>", "(deprecated, ignored) organization is derived from login").requiredOption("-e, --email <email>", "Email address").option("-n, --name <name>", "First name").option("--surname <surname>", "Last name").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(USERS_CREATE_EXAMPLES).trackedAction(processContext, async (username, options) => {
2225
+ warnDeprecatedOrganization4(options.organization);
2226
+ const [error, result] = await catchError((async () => {
2227
+ const { api, organizationId } = await createApiClient(UserApi, {
2228
+ loginValidity: options.loginValidity
2229
+ });
2230
+ const orgId = organizationId;
2231
+ const createCommand = {
2232
+ partitionGlobalId: orgId,
2233
+ userName: username,
2234
+ email: options.email,
2235
+ name: options.name,
2236
+ surname: options.surname
2237
+ };
2238
+ return await api.userCreateUser({
2239
+ createUserCommand: createCommand
2240
+ });
2241
+ })());
2242
+ if (error) {
2243
+ OutputFormatter.error({
2244
+ Result: RESULTS.Failure,
2245
+ Message: await extractErrorMessage(error),
2246
+ Instructions: INSTRUCTIONS7.create
2247
+ });
2248
+ processContext.exit(1);
2249
+ return;
2250
+ }
2251
+ OutputFormatter.success({
2252
+ Result: RESULTS.Success,
2253
+ Code: "UserCreated",
2254
+ Data: result
2255
+ });
2256
+ });
2257
+ users.command("update").description("Update an existing user. Use 'users list' to retrieve the user ID.").argument("<user-id>", "User ID (UUID)").option("-e, --email <email>", "New email address").option("-n, --name <name>", "New first name").option("--surname <surname>", "New last name").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(USERS_UPDATE_EXAMPLES).trackedAction(processContext, async (userId, options) => {
2258
+ warnDeprecatedOrganization4(options.organization);
2259
+ if (options.email === undefined && options.name === undefined && options.surname === undefined) {
2260
+ OutputFormatter.error({
2261
+ Result: RESULTS.Failure,
2262
+ Message: "No fields to update",
2263
+ Instructions: "Provide at least one of --email, --name, or --surname."
2264
+ });
2265
+ processContext.exit(1);
2266
+ return;
2267
+ }
2268
+ const updateCommand = {};
2269
+ if (options.email !== undefined)
2270
+ updateCommand.email = options.email;
2271
+ if (options.name !== undefined)
2272
+ updateCommand.name = options.name;
2273
+ if (options.surname !== undefined)
2274
+ updateCommand.surname = options.surname;
2275
+ const [error, result] = await catchError((async () => {
2276
+ const { api } = await createApiClient(UserApi, {
2277
+ loginValidity: options.loginValidity
2278
+ });
2279
+ return await api.userUpdate({
2280
+ userId,
2281
+ updateUserCommand: updateCommand
2282
+ });
2283
+ })());
2284
+ if (error) {
2285
+ OutputFormatter.error({
2286
+ Result: RESULTS.Failure,
2287
+ Message: await extractErrorMessage(error),
2288
+ Instructions: INSTRUCTIONS7.update
2289
+ });
2290
+ processContext.exit(1);
2291
+ return;
2292
+ }
2293
+ OutputFormatter.success({
2294
+ Result: RESULTS.Success,
2295
+ Code: "UserUpdated",
2296
+ Data: result
2297
+ });
2298
+ });
2299
+ users.command("delete").description("Delete a user by ID. Use 'users list' to retrieve the user ID.").argument("<user-id>", "User ID (UUID)").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(USERS_DELETE_EXAMPLES).trackedAction(processContext, async (userId, options) => {
2300
+ warnDeprecatedOrganization4(options.organization);
2301
+ const [error] = await catchError((async () => {
2302
+ const { api } = await createApiClient(UserApi, {
2303
+ loginValidity: options.loginValidity
2304
+ });
2305
+ return await api.userDelete({ userId });
2306
+ })());
2307
+ if (error) {
2308
+ OutputFormatter.error({
2309
+ Result: RESULTS.Failure,
2310
+ Message: await extractErrorMessage(error),
2311
+ Instructions: INSTRUCTIONS7.delete
2312
+ });
2313
+ processContext.exit(1);
2314
+ return;
2315
+ }
2316
+ OutputFormatter.success({
2317
+ Result: RESULTS.Success,
2318
+ Code: "UserDeleted",
2319
+ Data: {
2320
+ Id: userId,
2321
+ Status: "Deleted successfully"
2322
+ }
2323
+ });
2324
+ });
2325
+ users.command("invite").description("Invite users by email. Sends an invitation to join the organization.").requiredOption("-e, --email <emails>", "Comma-separated email addresses to invite").option("-n, --name <name>", "First name for the invited user").option("--surname <surname>", "Last name for the invited user").option("--login-validity <minutes>", "Override token validity (minutes)", (v) => Number.parseInt(v, 10)).examples(USERS_INVITE_EXAMPLES).trackedAction(processContext, async (options) => {
2326
+ warnDeprecatedOrganization4(options.organization);
2327
+ const [error, result] = await catchError((async () => {
2328
+ const { config } = await createIdentityConfig({
2329
+ loginValidity: options.loginValidity
2330
+ });
2331
+ const baseUrl = config.basePath.replace(/\/[^/]+\/identity_$/, "");
2332
+ const redirectUrl = `${baseUrl}/portal_/cloudrpa`;
2333
+ const api = new UserApi(config);
2334
+ const invitedUsers = options.email.split(",").map((e) => ({
2335
+ email: e.trim(),
2336
+ name: options.name,
2337
+ surname: options.surname,
2338
+ redirectUrl
2339
+ }));
2340
+ return await api.userInviteUsers({
2341
+ invitedUser: invitedUsers
2342
+ });
2343
+ })());
2344
+ if (error) {
2345
+ OutputFormatter.error({
2346
+ Result: RESULTS.Failure,
2347
+ Message: await extractErrorMessage(error),
2348
+ Instructions: INSTRUCTIONS7.invite
2349
+ });
2350
+ processContext.exit(1);
2351
+ return;
2352
+ }
2353
+ OutputFormatter.success({
2354
+ Result: RESULTS.Success,
2355
+ Code: "UsersInvited",
2356
+ Data: result
2357
+ });
2358
+ });
2359
+ };
2360
+
2361
+ // ../identity-commands/src/index.ts
2362
+ var registerCommands = async (program) => {
2363
+ registerExternalAppsCommand(program);
2364
+ registerGroupsCommand(program);
2365
+ registerPatCommand(program);
2366
+ registerRobotAccountsCommand(program);
2367
+ registerScopesCommand(program);
2368
+ registerSmtpCommand(program);
2369
+ registerUsersCommand(program);
2370
+ };
2371
+ export {
2372
+ registerCommands
2373
+ };
2374
+
2375
+ //# debugId=BCA0BD64AB49604664756E2164756E21