@pnp/cli-microsoft365 8.0.0-beta.e6f9331 → 8.1.0-beta.309a9b8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/.eslintrc.cjs +1 -0
  2. package/allCommands.json +1 -1
  3. package/allCommandsFull.json +1 -1
  4. package/dist/Auth.js +10 -18
  5. package/dist/Command.js +50 -5
  6. package/dist/chili/chili.js +0 -23
  7. package/dist/cli/cli.js +100 -100
  8. package/dist/m365/commands/login.js +49 -96
  9. package/dist/m365/commands/setup.js +0 -4
  10. package/dist/m365/connection/commands/connection-remove.js +6 -2
  11. package/dist/m365/connection/commands/connection-set.js +4 -1
  12. package/dist/m365/connection/commands/connection-use.js +25 -4
  13. package/dist/m365/entra/commands/enterpriseapp/enterpriseapp-remove.js +123 -0
  14. package/dist/m365/entra/commands/group/group-set.js +256 -0
  15. package/dist/m365/entra/commands/m365group/m365group-set.js +66 -29
  16. package/dist/m365/entra/commands/m365group/m365group-user-add.js +109 -32
  17. package/dist/m365/entra/commands/m365group/m365group-user-set.js +159 -84
  18. package/dist/m365/entra/commands/multitenant/MultitenantOrganization.js +2 -0
  19. package/dist/m365/entra/commands/multitenant/multitenant-add.js +65 -0
  20. package/dist/m365/entra/commands/multitenant/multitenant-get.js +32 -0
  21. package/dist/m365/entra/commands/multitenant/multitenant-remove.js +118 -0
  22. package/dist/m365/entra/commands/multitenant/multitenant-set.js +72 -0
  23. package/dist/m365/entra/commands.js +7 -0
  24. package/dist/m365/external/commands/connection/connection-doctor.js +10 -24
  25. package/dist/m365/flow/commands/flow-get.js +1 -1
  26. package/dist/m365/flow/commands/flow-list.js +2 -1
  27. package/dist/m365/graph/commands/subscription/subscription-add.js +4 -2
  28. package/dist/m365/onenote/commands/notebook/notebook-add.js +132 -0
  29. package/dist/m365/onenote/commands.js +1 -0
  30. package/dist/m365/pa/commands/app/app-export.js +13 -7
  31. package/dist/m365/spe/ContainerTypeProperties.js +2 -0
  32. package/dist/m365/spe/commands/containertype/containertype-list.js +49 -0
  33. package/dist/m365/spe/commands.js +2 -1
  34. package/dist/m365/spfx/commands/project/base-project-command.js +36 -126
  35. package/dist/m365/spo/commands/applicationcustomizer/applicationcustomizer-get.js +16 -21
  36. package/dist/m365/spo/commands/commandset/commandset-get.js +31 -17
  37. package/dist/m365/spo/commands/contenttype/contenttype-field-list.js +124 -0
  38. package/dist/m365/spo/commands/field/field-list.js +1 -1
  39. package/dist/m365/spo/commands/file/file-roleassignment-add.js +1 -1
  40. package/dist/m365/spo/commands/file/file-roleinheritance-break.js +1 -1
  41. package/dist/m365/spo/commands/file/file-roleinheritance-reset.js +1 -1
  42. package/dist/m365/spo/commands/folder/folder-retentionlabel-ensure.js +1 -1
  43. package/dist/m365/spo/commands/folder/folder-sharinglink-get.js +86 -0
  44. package/dist/m365/spo/commands/folder/folder-sharinglink-list.js +110 -0
  45. package/dist/m365/spo/commands/list/ListInstance.js +6 -1
  46. package/dist/m365/spo/commands/list/list-get.js +9 -3
  47. package/dist/m365/spo/commands/list/list-roleassignment-add.js +46 -21
  48. package/dist/m365/spo/commands/list/list-roleassignment-remove.js +48 -46
  49. package/dist/m365/spo/commands/page/page-clientsidewebpart-add.js +2 -3
  50. package/dist/m365/spo/commands/page/page-text-add.js +2 -3
  51. package/dist/m365/spo/commands/site/site-get.js +12 -16
  52. package/dist/m365/spo/commands/spo-search.js +3 -4
  53. package/dist/m365/spo/commands/tenant/tenant-applicationcustomizer-get.js +19 -5
  54. package/dist/m365/spo/commands/tenant/tenant-commandset-get.js +20 -6
  55. package/dist/m365/spo/commands.js +3 -0
  56. package/dist/m365/teams/commands/meeting/meeting-attendancereport-get.js +119 -0
  57. package/dist/m365/teams/commands/message/message-remove.js +112 -0
  58. package/dist/m365/teams/commands/message/message-restore.js +106 -0
  59. package/dist/m365/teams/commands.js +3 -0
  60. package/dist/m365/viva/commands/engage/engage-community-add.js +166 -0
  61. package/dist/m365/viva/commands.js +1 -0
  62. package/dist/utils/drive.js +61 -0
  63. package/dist/utils/formatting.js +30 -1
  64. package/dist/utils/spo.js +69 -6
  65. package/dist/utils/teams.js +49 -0
  66. package/dist/utils/zod.js +124 -0
  67. package/docs/docs/cmd/connection/connection-use.mdx +8 -2
  68. package/docs/docs/cmd/entra/enterpriseapp/enterpriseapp-remove.mdx +65 -0
  69. package/docs/docs/cmd/entra/group/group-add.mdx +0 -4
  70. package/docs/docs/cmd/entra/group/group-set.mdx +89 -0
  71. package/docs/docs/cmd/entra/m365group/m365group-set.mdx +37 -7
  72. package/docs/docs/cmd/entra/m365group/m365group-user-add.mdx +28 -10
  73. package/docs/docs/cmd/entra/m365group/m365group-user-set.mdx +35 -11
  74. package/docs/docs/cmd/entra/multitenant/multitenant-add.mdx +107 -0
  75. package/docs/docs/cmd/entra/multitenant/multitenant-get.mdx +94 -0
  76. package/docs/docs/cmd/entra/multitenant/multitenant-remove.mdx +58 -0
  77. package/docs/docs/cmd/entra/multitenant/multitenant-set.mdx +53 -0
  78. package/docs/docs/cmd/external/connection/connection-doctor.mdx +9 -9
  79. package/docs/docs/cmd/flow/flow-get.mdx +149 -283
  80. package/docs/docs/cmd/graph/subscription/subscription-add.mdx +18 -0
  81. package/docs/docs/cmd/onenote/notebook/notebook-add.mdx +169 -0
  82. package/docs/docs/cmd/pa/app/app-export.mdx +15 -9
  83. package/docs/docs/cmd/planner/plan/plan-remove.mdx +1 -1
  84. package/docs/docs/cmd/spe/containertype/containertype-list.mdx +102 -0
  85. package/docs/docs/cmd/spo/app/app-uninstall.mdx +1 -1
  86. package/docs/docs/cmd/spo/applicationcustomizer/applicationcustomizer-get.mdx +87 -38
  87. package/docs/docs/cmd/spo/applicationcustomizer/applicationcustomizer-list.mdx +22 -28
  88. package/docs/docs/cmd/spo/commandset/commandset-get.mdx +75 -24
  89. package/docs/docs/cmd/spo/commandset/commandset-list.mdx +26 -32
  90. package/docs/docs/cmd/spo/contenttype/contenttype-field-list.mdx +172 -0
  91. package/docs/docs/cmd/spo/contenttype/contenttype-list.mdx +3 -3
  92. package/docs/docs/cmd/spo/field/field-list.mdx +3 -3
  93. package/docs/docs/cmd/spo/file/file-retentionlabel-ensure.mdx +1 -1
  94. package/docs/docs/cmd/spo/file/file-roleassignment-add.mdx +2 -2
  95. package/docs/docs/cmd/spo/file/file-roleassignment-remove.mdx +1 -1
  96. package/docs/docs/cmd/spo/file/file-roleinheritance-break.mdx +1 -1
  97. package/docs/docs/cmd/spo/file/file-roleinheritance-reset.mdx +1 -1
  98. package/docs/docs/cmd/spo/folder/folder-retentionlabel-ensure.mdx +2 -2
  99. package/docs/docs/cmd/spo/folder/folder-sharinglink-get.mdx +110 -0
  100. package/docs/docs/cmd/spo/folder/folder-sharinglink-list.mdx +114 -0
  101. package/docs/docs/cmd/spo/list/list-get.mdx +6 -0
  102. package/docs/docs/cmd/spo/list/list-roleassignment-add.mdx +15 -3
  103. package/docs/docs/cmd/spo/list/list-roleassignment-remove.mdx +15 -3
  104. package/docs/docs/cmd/spo/listitem/listitem-retentionlabel-ensure.mdx +4 -4
  105. package/docs/docs/cmd/spo/listitem/listitem-retentionlabel-remove.mdx +1 -1
  106. package/docs/docs/cmd/spo/listitem/listitem-roleassignment-add.mdx +9 -9
  107. package/docs/docs/cmd/spo/listitem/listitem-roleassignment-remove.mdx +7 -7
  108. package/docs/docs/cmd/spo/site/site-recyclebinitem-list.mdx +1 -1
  109. package/docs/docs/cmd/spo/tenant/tenant-applicationcustomizer-get.mdx +79 -30
  110. package/docs/docs/cmd/spo/tenant/tenant-applicationcustomizer-list.mdx +20 -19
  111. package/docs/docs/cmd/spo/tenant/tenant-commandset-get.mdx +84 -38
  112. package/docs/docs/cmd/spo/tenant/tenant-commandset-list.mdx +20 -19
  113. package/docs/docs/cmd/spo/web/web-roleassignment-add.mdx +1 -1
  114. package/docs/docs/cmd/spo/web/web-roleassignment-remove.mdx +1 -1
  115. package/docs/docs/cmd/teams/meeting/meeting-attendancereport-get.mdx +138 -0
  116. package/docs/docs/cmd/teams/meeting/meeting-list.mdx +7 -3
  117. package/docs/docs/cmd/teams/message/message-remove.mdx +64 -0
  118. package/docs/docs/cmd/teams/message/message-restore.mdx +62 -0
  119. package/docs/docs/cmd/viva/engage/engage-community-add.mdx +168 -0
  120. package/npm-shrinkwrap.json +987 -1327
  121. package/package.json +27 -24
package/dist/Auth.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AzureCloudInstance } from '@azure/msal-common';
2
+ import assert from 'assert';
2
3
  import { CommandError } from './Command.js';
3
4
  import { FileTokenStorage } from './auth/FileTokenStorage.js';
4
5
  import { msalCachePlugin } from './auth/msalCachePlugin.js';
@@ -6,16 +7,15 @@ import { cli } from './cli/cli.js';
6
7
  import config from './config.js';
7
8
  import request from './request.js';
8
9
  import { settingsNames } from './settingsNames.js';
9
- import { browserUtil } from './utils/browserUtil.js';
10
10
  import * as accessTokenUtil from './utils/accessToken.js';
11
- import assert from 'assert';
11
+ import { browserUtil } from './utils/browserUtil.js';
12
12
  export var CloudType;
13
13
  (function (CloudType) {
14
- CloudType[CloudType["Public"] = 0] = "Public";
15
- CloudType[CloudType["USGov"] = 1] = "USGov";
16
- CloudType[CloudType["USGovHigh"] = 2] = "USGovHigh";
17
- CloudType[CloudType["USGovDoD"] = 3] = "USGovDoD";
18
- CloudType[CloudType["China"] = 4] = "China";
14
+ CloudType["Public"] = "Public";
15
+ CloudType["USGov"] = "USGov";
16
+ CloudType["USGovHigh"] = "USGovHigh";
17
+ CloudType["USGovDoD"] = "USGovDoD";
18
+ CloudType["China"] = "China";
19
19
  })(CloudType || (CloudType = {}));
20
20
  export class Connection {
21
21
  constructor() {
@@ -354,15 +354,7 @@ export class Auth {
354
354
  await logger.logToStderr(response);
355
355
  await logger.logToStderr('');
356
356
  }
357
- cli.spinner.text = response.message;
358
- cli.spinner.spinner = {
359
- frames: ['🌶️ ']
360
- };
361
- // don't show spinner if running tests
362
- /* c8 ignore next 3 */
363
- if (!cli.spinner.isSpinning && typeof global.it === 'undefined') {
364
- cli.spinner.start();
365
- }
357
+ await logger.logToStderr(`🌶️ ${response.message}`);
366
358
  if (cli.getSettingWithDefaultValue(settingsNames.autoOpenLinksInBrowser, false)) {
367
359
  await browserUtil.open(response.verificationUri);
368
360
  }
@@ -699,7 +691,7 @@ export class Auth {
699
691
  const allConnections = await this.getAllConnections();
700
692
  const connection = allConnections.find(i => i.name === name);
701
693
  if (!connection) {
702
- throw new CommandError(`The connection '${name}' cannot be found`);
694
+ throw new CommandError(`The connection '${name}' cannot be found.`);
703
695
  }
704
696
  return connection;
705
697
  }
@@ -718,7 +710,7 @@ export class Auth {
718
710
  return details;
719
711
  }
720
712
  }
721
- Auth.cloudEndpoints = [];
713
+ Auth.cloudEndpoints = {};
722
714
  Auth.initialize();
723
715
  export default new Auth();
724
716
  //# sourceMappingURL=Auth.js.map
package/dist/Command.js CHANGED
@@ -5,6 +5,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
5
5
  };
6
6
  var _Command_instances, _Command_initTelemetry, _Command_initOptions, _Command_initValidators;
7
7
  import os from 'os';
8
+ import { z } from 'zod';
8
9
  import auth from './Auth.js';
9
10
  import { cli } from './cli/cli.js';
10
11
  import request from './request.js';
@@ -13,6 +14,7 @@ import { telemetry } from './telemetry.js';
13
14
  import { accessToken } from './utils/accessToken.js';
14
15
  import { md } from './utils/md.js';
15
16
  import { prompt } from './utils/prompt.js';
17
+ import { zod } from './utils/zod.js';
16
18
  export class CommandError {
17
19
  constructor(message, code) {
18
20
  this.message = message;
@@ -25,10 +27,26 @@ export class CommandErrorWithOutput {
25
27
  this.stderr = stderr;
26
28
  }
27
29
  }
30
+ export const globalOptionsZod = z.object({
31
+ query: z.string().optional(),
32
+ output: zod.alias('o', z.enum(['csv', 'json', 'md', 'text', 'none']).optional()),
33
+ debug: z.boolean().default(false),
34
+ verbose: z.boolean().default(false)
35
+ });
28
36
  class Command {
29
37
  get allowedOutputs() {
30
38
  return ['csv', 'json', 'md', 'text', 'none'];
31
39
  }
40
+ get schema() {
41
+ return undefined;
42
+ }
43
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
44
+ getRefinedSchema(schema) {
45
+ return undefined;
46
+ }
47
+ getSchemaToParse() {
48
+ return this.getRefinedSchema(this.schema) ?? this.schema;
49
+ }
32
50
  constructor() {
33
51
  // These functions must be defined with # so that they're truly private
34
52
  // otherwise you'll get a ts2415 error (Types have separate declarations of
@@ -48,6 +66,9 @@ class Command {
48
66
  string: []
49
67
  };
50
68
  this.validators = [];
69
+ // metadata for command's options
70
+ // used for building telemetry
71
+ this.optionsInfo = [];
51
72
  __classPrivateFieldGet(this, _Command_instances, "m", _Command_initTelemetry).call(this);
52
73
  __classPrivateFieldGet(this, _Command_instances, "m", _Command_initOptions).call(this);
53
74
  __classPrivateFieldGet(this, _Command_instances, "m", _Command_initValidators).call(this);
@@ -90,9 +111,7 @@ class Command {
90
111
  prompted = true;
91
112
  await cli.error('🌶️ Provide values for the following parameters:');
92
113
  }
93
- const answer = optionInfo.autocomplete !== undefined
94
- ? await prompt.forSelection({ message: `${optionInfo.name}: `, choices: optionInfo.autocomplete.map((choice) => { return { name: choice, value: choice }; }) })
95
- : await prompt.forInput({ message: `${optionInfo.name}: ` });
114
+ const answer = await cli.promptForValue(optionInfo);
96
115
  args.options[optionInfo.name] = answer;
97
116
  }
98
117
  if (prompted) {
@@ -410,8 +429,34 @@ class Command {
410
429
  return '';
411
430
  }
412
431
  getTelemetryProperties(args) {
413
- this.telemetry.forEach(t => t(args));
414
- return this.telemetryProperties;
432
+ if (this.schema) {
433
+ const telemetryProperties = {};
434
+ this.optionsInfo.forEach(o => {
435
+ if (o.required) {
436
+ return;
437
+ }
438
+ if (typeof args.options[o.name] === 'undefined') {
439
+ return;
440
+ }
441
+ switch (o.type) {
442
+ case 'string':
443
+ telemetryProperties[o.name] = o.autocomplete ? args.options[o.name] : typeof args.options[o.name] !== 'undefined';
444
+ break;
445
+ case 'boolean':
446
+ telemetryProperties[o.name] = args.options[o.name];
447
+ break;
448
+ case 'number':
449
+ telemetryProperties[o.name] = typeof args.options[o.name] !== 'undefined';
450
+ break;
451
+ }
452
+ ;
453
+ });
454
+ return telemetryProperties;
455
+ }
456
+ else {
457
+ this.telemetry.forEach(t => t(args));
458
+ return this.telemetryProperties;
459
+ }
415
460
  }
416
461
  async getTextOutput(logStatement) {
417
462
  // display object as a list of key-value pairs
@@ -1,22 +1,17 @@
1
1
  import fs from 'fs';
2
- import ora from 'ora';
3
2
  import path from 'path';
4
3
  import url from 'url';
5
- import { cli } from '../cli/cli.js';
6
4
  import request from '../request.js';
7
- import { settingsNames } from '../settingsNames.js';
8
5
  import { md } from '../utils/md.js';
9
6
  import { prompt } from '../utils/prompt.js';
10
7
  const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
11
8
  const mendableBaseUrl = 'https://api.mendable.ai/v1';
12
9
  const mendableApiKey = 'd3313d54-6f8e-40e0-90d3-4095019d4be7';
13
- const spinner = ora({ discardStdin: false });
14
10
  let showHelp = false;
15
11
  let debug = false;
16
12
  let conversationId = 0;
17
13
  let initialPrompt = '';
18
14
  let history = [];
19
- const showSpinner = cli.getSettingWithDefaultValue(settingsNames.showSpinner, true) && typeof global.it === 'undefined';
20
15
  request.logger = {
21
16
  /* c8 ignore next 3 */
22
17
  log: async (msg) => console.log(msg),
@@ -74,20 +69,11 @@ async function promptForPrompt() {
74
69
  }
75
70
  async function runConversationTurn(conversationId, question) {
76
71
  console.log('');
77
- /* c8 ignore next 4 */
78
- if (showSpinner) {
79
- spinner.text = 'Searching documentation...';
80
- spinner.start();
81
- }
82
72
  const response = await runMendableChat(conversationId, question);
83
73
  history.push({
84
74
  prompt: question,
85
75
  response: response.answer.text
86
76
  });
87
- /* c8 ignore next 3 */
88
- if (showSpinner) {
89
- spinner.stop();
90
- }
91
77
  console.log(md.md2plain(response.answer.text, ''));
92
78
  console.log('');
93
79
  console.log('Source:');
@@ -141,16 +127,7 @@ async function endConversation(conversationId) {
141
127
  conversation_id: conversationId
142
128
  }
143
129
  };
144
- /* c8 ignore next 4 */
145
- if (showSpinner) {
146
- spinner.text = 'Ending conversation...';
147
- spinner.start();
148
- }
149
130
  await request.post(requestOptions);
150
- /* c8 ignore next 3 */
151
- if (showSpinner) {
152
- spinner.stop();
153
- }
154
131
  }
155
132
  async function runMendableChat(conversationId, question) {
156
133
  const requestOptions = {
package/dist/cli/cli.js CHANGED
@@ -1,29 +1,27 @@
1
1
  import Configstore from 'configstore';
2
2
  import fs from 'fs';
3
- import minimist from 'minimist';
4
3
  import { createRequire } from 'module';
5
- import ora from 'ora';
6
4
  import os from 'os';
7
5
  import path from 'path';
8
6
  import { fileURLToPath, pathToFileURL } from 'url';
7
+ import yargs from 'yargs-parser';
8
+ import { ZodError } from 'zod';
9
9
  import Command, { CommandError } from '../Command.js';
10
10
  import config from '../config.js';
11
11
  import request from '../request.js';
12
12
  import { settingsNames } from '../settingsNames.js';
13
13
  import { telemetry } from '../telemetry.js';
14
14
  import { app } from '../utils/app.js';
15
+ import { browserUtil } from '../utils/browserUtil.js';
15
16
  import { formatting } from '../utils/formatting.js';
16
17
  import { md } from '../utils/md.js';
17
- import { validation } from '../utils/validation.js';
18
18
  import { prompt } from '../utils/prompt.js';
19
+ import { validation } from '../utils/validation.js';
20
+ import { zod } from '../utils/zod.js';
19
21
  import { timings } from './timings.js';
20
- import { browserUtil } from '../utils/browserUtil.js';
21
22
  const require = createRequire(import.meta.url);
22
23
  const __dirname = fileURLToPath(new URL('.', import.meta.url));
23
24
  let _config;
24
- // we assign it through exported function to support mocking
25
- // eslint-disable-next-line prefer-const
26
- let spinner = ora();
27
25
  const commands = [];
28
26
  /**
29
27
  * Command to execute
@@ -38,6 +36,14 @@ const defaultHelpMode = 'options';
38
36
  const defaultHelpTarget = 'console';
39
37
  const helpModes = ['options', 'examples', 'remarks', 'response', 'full'];
40
38
  const helpTargets = ['console', 'web'];
39
+ const yargsConfiguration = {
40
+ 'parse-numbers': true,
41
+ 'strip-aliased': true,
42
+ 'strip-dashed': true,
43
+ 'dot-notation': false,
44
+ 'boolean-negation': true,
45
+ 'camel-case-expansion': false
46
+ };
41
47
  function getConfig() {
42
48
  if (!_config) {
43
49
  _config = new Configstore(config.configstoreName);
@@ -68,7 +74,7 @@ async function execute(rawArgs) {
68
74
  rawArgs.shift();
69
75
  }
70
76
  // parse args to see if a command has been specified
71
- const parsedArgs = minimist(rawArgs);
77
+ const parsedArgs = yargs(rawArgs);
72
78
  // load command
73
79
  await cli.loadCommandFromArgs(parsedArgs._);
74
80
  if (cli.commandToExecute) {
@@ -81,8 +87,7 @@ async function execute(rawArgs) {
81
87
  };
82
88
  }
83
89
  catch (e) {
84
- const optionsWithoutShorts = removeShortOptions({ options: parsedArgs });
85
- return cli.closeWithError(e.message, optionsWithoutShorts, false);
90
+ return cli.closeWithError(e.message, { options: parsedArgs }, false);
86
91
  }
87
92
  }
88
93
  else {
@@ -130,18 +135,54 @@ async function execute(rawArgs) {
130
135
  if (cli.optionsFromArgs.options.output === undefined) {
131
136
  cli.optionsFromArgs.options.output = cli.getSettingWithDefaultValue(settingsNames.output, 'json');
132
137
  }
133
- const startValidation = process.hrtime.bigint();
134
- const validationResult = await cli.commandToExecute.command.validate(cli.optionsFromArgs, cli.commandToExecute);
135
- const endValidation = process.hrtime.bigint();
136
- timings.validation.push(Number(endValidation - startValidation));
137
- if (validationResult !== true) {
138
- return cli.closeWithError(validationResult, cli.optionsFromArgs, true);
138
+ let finalArgs = cli.optionsFromArgs.options;
139
+ if (cli.commandToExecute?.command.schema) {
140
+ while (true) {
141
+ const startValidation = process.hrtime.bigint();
142
+ const result = cli.commandToExecute.command.getSchemaToParse().safeParse(cli.optionsFromArgs.options);
143
+ const endValidation = process.hrtime.bigint();
144
+ timings.validation.push(Number(endValidation - startValidation));
145
+ if (result.success) {
146
+ finalArgs = result.data;
147
+ break;
148
+ }
149
+ else {
150
+ const hasNonRequiredErrors = result.error.errors.some(e => e.code !== 'invalid_type' || e.received !== 'undefined');
151
+ const shouldPrompt = cli.getSettingWithDefaultValue(settingsNames.prompt, true);
152
+ if (hasNonRequiredErrors === false &&
153
+ shouldPrompt) {
154
+ await cli.error('🌶️ Provide values for the following parameters:');
155
+ for (const error of result.error.errors) {
156
+ const optionInfo = cli.commandToExecute.options.find(o => o.name === error.path.join('.'));
157
+ const answer = await cli.promptForValue(optionInfo);
158
+ cli.optionsFromArgs.options[error.path.join('.')] = answer;
159
+ }
160
+ }
161
+ else {
162
+ result.error.errors.forEach(e => {
163
+ if (e.code === 'invalid_type' &&
164
+ e.received === 'undefined') {
165
+ e.message = `Required option not specified`;
166
+ }
167
+ });
168
+ return cli.closeWithError(result.error, cli.optionsFromArgs, true);
169
+ }
170
+ }
171
+ }
172
+ }
173
+ else {
174
+ const startValidation = process.hrtime.bigint();
175
+ const validationResult = await cli.commandToExecute.command.validate(cli.optionsFromArgs, cli.commandToExecute);
176
+ const endValidation = process.hrtime.bigint();
177
+ timings.validation.push(Number(endValidation - startValidation));
178
+ if (validationResult !== true) {
179
+ return cli.closeWithError(validationResult, cli.optionsFromArgs, true);
180
+ }
139
181
  }
140
- cli.optionsFromArgs = removeShortOptions(cli.optionsFromArgs);
141
182
  const end = process.hrtime.bigint();
142
183
  timings.core.push(Number(end - start));
143
184
  try {
144
- await cli.executeCommand(cli.commandToExecute.command, cli.optionsFromArgs);
185
+ await cli.executeCommand(cli.commandToExecute.command, { options: finalArgs });
145
186
  const endTotal = process.hrtime.bigint();
146
187
  timings.total.push(Number(endTotal - start));
147
188
  await printTimings(rawArgs);
@@ -190,12 +231,6 @@ async function executeCommand(command, args) {
190
231
  // the command to execute
191
232
  const parentCommandName = cli.currentCommandName;
192
233
  cli.currentCommandName = command.getCommandName(cli.currentCommandName);
193
- const showSpinner = cli.getSettingWithDefaultValue(settingsNames.showSpinner, true) && args.options.output !== 'none';
194
- // don't show spinner if running tests
195
- /* c8 ignore next 3 */
196
- if (showSpinner && typeof global.it === 'undefined') {
197
- cli.spinner.start();
198
- }
199
234
  const startCommand = process.hrtime.bigint();
200
235
  try {
201
236
  await command.action(logger, args);
@@ -207,10 +242,6 @@ async function executeCommand(command, args) {
207
242
  finally {
208
243
  // restore the original command name
209
244
  cli.currentCommandName = parentCommandName;
210
- /* c8 ignore next 3 */
211
- if (cli.spinner.isSpinning) {
212
- cli.spinner.stop();
213
- }
214
245
  const endCommand = process.hrtime.bigint();
215
246
  timings.command.push(Number(endCommand - startCommand));
216
247
  }
@@ -361,12 +392,14 @@ async function loadCommandFromFile(commandFileUrl) {
361
392
  catch { }
362
393
  }
363
394
  function getCommandInfo(command, filePath = '', helpFilePath = '') {
395
+ const options = command.schema ? zod.schemaToOptions(command.schema) : getCommandOptions(command);
396
+ command.optionsInfo = options;
364
397
  return {
365
398
  aliases: command.alias(),
366
399
  name: command.name,
367
400
  description: command.description,
368
401
  command: command,
369
- options: getCommandOptions(command),
402
+ options,
370
403
  defaultProperties: command.defaultProperties(),
371
404
  file: filePath,
372
405
  help: helpFilePath
@@ -401,36 +434,43 @@ function getCommandOptions(command) {
401
434
  return options;
402
435
  }
403
436
  function getCommandOptionsFromArgs(args, commandInfo) {
404
- const minimistOptions = {
405
- alias: {}
437
+ const yargsOptions = {
438
+ alias: {},
439
+ configuration: yargsConfiguration
406
440
  };
407
441
  let argsToParse = args;
408
442
  if (commandInfo) {
409
- const commandTypes = commandInfo.command.types;
410
- if (commandTypes) {
411
- minimistOptions.string = commandTypes.string;
412
- // minimist will parse unused boolean options to 'false' (unused options => options that are not included in the args)
413
- // But in the CLI booleans are nullable. They can can be true, false or undefined.
414
- // For this reason we only pass boolean types that are actually used as arg.
415
- minimistOptions.boolean = commandTypes.boolean.filter(optionName => args.some(arg => `--${optionName}` === arg || `-${optionName}` === arg));
416
- }
417
- minimistOptions.alias = {};
443
+ if (commandInfo.command.schema) {
444
+ yargsOptions.string = commandInfo.options.filter(o => o.type === 'string').map(o => o.name);
445
+ yargsOptions.boolean = commandInfo.options.filter(o => o.type === 'boolean').map(o => o.name);
446
+ yargsOptions.number = commandInfo.options.filter(o => o.type === 'number').map(o => o.name);
447
+ argsToParse = getRewrittenArgs(args, yargsOptions.boolean);
448
+ }
449
+ else {
450
+ const commandTypes = commandInfo.command.types;
451
+ if (commandTypes) {
452
+ yargsOptions.string = commandTypes.string;
453
+ // minimist will parse unused boolean options to 'false' (unused options => options that are not included in the args)
454
+ // But in the CLI booleans are nullable. They can can be true, false or undefined.
455
+ // For this reason we only pass boolean types that are actually used as arg.
456
+ yargsOptions.boolean = commandTypes.boolean.filter(optionName => args.some(arg => `--${optionName}` === arg || `-${optionName}` === arg));
457
+ }
458
+ argsToParse = getRewrittenArgs(args, commandTypes.boolean);
459
+ }
418
460
  commandInfo.options.forEach(option => {
419
461
  if (option.short && option.long) {
420
- minimistOptions.alias[option.short] = option.long;
462
+ yargsOptions.alias[option.long] = option.short;
421
463
  }
422
464
  });
423
- argsToParse = getRewrittenArgs(args, commandTypes);
424
465
  }
425
- return minimist(argsToParse, minimistOptions);
466
+ return yargs(argsToParse, yargsOptions);
426
467
  }
427
468
  /**
428
469
  * Rewrites arguments (if necessary) before passing them into minimist.
429
470
  * Currently only boolean values are checked and fixed.
430
471
  * Args are only checked and rewritten if the option has been added to the 'types.boolean' array.
431
472
  */
432
- function getRewrittenArgs(args, commandTypes) {
433
- const booleanTypes = commandTypes.boolean;
473
+ function getRewrittenArgs(args, booleanTypes) {
434
474
  if (booleanTypes.length === 0) {
435
475
  return args;
436
476
  }
@@ -736,6 +776,9 @@ async function closeWithError(error, args, showHelpIfEnabled = false) {
736
776
  return process.exit(exitCode);
737
777
  }
738
778
  let errorMessage = error instanceof CommandError ? error.message : error;
779
+ if (error instanceof ZodError) {
780
+ errorMessage = error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(os.EOL);
781
+ }
739
782
  if ((!args.options.output || args.options.output === 'json') &&
740
783
  !cli.getSettingWithDefaultValue(settingsNames.printErrorsAsPlainText, true)) {
741
784
  errorMessage = JSON.stringify({ error: errorMessage });
@@ -758,29 +801,14 @@ async function closeWithError(error, args, showHelpIfEnabled = false) {
758
801
  /* c8 ignore next */
759
802
  }
760
803
  function log(message, ...optionalParams) {
761
- const spinnerSpinning = cli.spinner.isSpinning;
762
- /* c8 ignore next 3 */
763
- if (spinnerSpinning) {
764
- cli.spinner.stop();
765
- }
766
804
  if (message) {
767
805
  console.log(message, ...optionalParams);
768
806
  }
769
807
  else {
770
808
  console.log();
771
809
  }
772
- // Restart the spinner if it was running before the log
773
- /* c8 ignore next 3 */
774
- if (spinnerSpinning) {
775
- cli.spinner.start();
776
- }
777
810
  }
778
811
  async function error(message, ...optionalParams) {
779
- const spinnerSpinning = cli.spinner.isSpinning;
780
- /* c8 ignore next 3 */
781
- if (spinnerSpinning) {
782
- cli.spinner.stop();
783
- }
784
812
  const errorOutput = cli.getSettingWithDefaultValue(settingsNames.errorOutput, 'stderr');
785
813
  if (errorOutput === 'stdout') {
786
814
  console.log(message, ...optionalParams);
@@ -788,40 +816,25 @@ async function error(message, ...optionalParams) {
788
816
  else {
789
817
  console.error(message, ...optionalParams);
790
818
  }
791
- // Restart the spinner if it was running before the log
792
- /* c8 ignore next 3 */
793
- if (spinnerSpinning) {
794
- cli.spinner.start();
795
- }
819
+ }
820
+ async function promptForValue(optionInfo) {
821
+ return optionInfo.autocomplete !== undefined
822
+ ? await prompt.forSelection({
823
+ message: `${optionInfo.name}: `,
824
+ choices: optionInfo.autocomplete.map((choice) => {
825
+ return { name: choice, value: choice };
826
+ })
827
+ })
828
+ : await prompt.forInput({ message: `${optionInfo.name}: ` });
796
829
  }
797
830
  async function promptForSelection(config) {
798
- const spinnerSpinning = cli.spinner.isSpinning;
799
- /* c8 ignore next 3 */
800
- if (spinnerSpinning) {
801
- cli.spinner.stop();
802
- }
803
831
  const answer = await prompt.forSelection(config);
804
832
  await cli.error('');
805
- // Restart the spinner if it was running before the prompt
806
- /* c8 ignore next 3 */
807
- if (spinnerSpinning) {
808
- cli.spinner.start();
809
- }
810
833
  return answer;
811
834
  }
812
835
  async function promptForConfirmation(config) {
813
- const spinnerSpinning = cli.spinner.isSpinning;
814
- /* c8 ignore next 3 */
815
- if (spinnerSpinning) {
816
- cli.spinner.stop();
817
- }
818
836
  const answer = await prompt.forConfirmation(config);
819
837
  await cli.error('');
820
- // Restart the spinner if it was running before the prompt
821
- /* c8 ignore next 3 */
822
- if (spinnerSpinning) {
823
- cli.spinner.start();
824
- }
825
838
  return answer;
826
839
  }
827
840
  async function handleMultipleResultsFound(message, values) {
@@ -834,13 +847,6 @@ async function handleMultipleResultsFound(message, values) {
834
847
  const response = await cli.promptForSelection({ message: `Please choose one:`, choices });
835
848
  return values[response];
836
849
  }
837
- function removeShortOptions(args) {
838
- const filteredArgs = JSON.parse(JSON.stringify(args));
839
- const optionsToRemove = Object.getOwnPropertyNames(args.options)
840
- .filter(option => option.length === 1 || option === '--');
841
- optionsToRemove.forEach(option => delete filteredArgs.options[option]);
842
- return filteredArgs;
843
- }
844
850
  function loadOptionValuesFromFiles(args) {
845
851
  const optionNames = Object.getOwnPropertyNames(args.options);
846
852
  optionNames.forEach(option => {
@@ -885,14 +891,8 @@ export const cli = {
885
891
  printAvailableCommands,
886
892
  promptForConfirmation,
887
893
  promptForSelection,
894
+ promptForValue,
888
895
  shouldTrimOutput,
889
- spinner
890
- };
891
- const spinnerOptions = {
892
- text: 'Running command...',
893
- /* c8 ignore next 1 */
894
- stream: cli.getSettingWithDefaultValue('errorOutput', 'stderr') === 'stderr' ? process.stderr : process.stdout,
895
- discardStdin: false
896
+ yargsConfiguration
896
897
  };
897
- cli.spinner = ora(spinnerOptions);
898
898
  //# sourceMappingURL=cli.js.map