@pnp/cli-microsoft365 9.0.0-beta.2f8dd1e → 9.0.0-beta.d6b190a

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 (67) 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 +9 -17
  5. package/dist/Command.js +49 -2
  6. package/dist/chili/chili.js +0 -23
  7. package/dist/cli/cli.js +61 -101
  8. package/dist/m365/commands/login.js +44 -96
  9. package/dist/m365/commands/setup.js +0 -4
  10. package/dist/m365/entra/commands/m365group/m365group-set.js +66 -29
  11. package/dist/m365/entra/commands/multitenant/MultitenantOrganization.js +2 -0
  12. package/dist/m365/entra/commands/multitenant/multitenant-get.js +32 -0
  13. package/dist/m365/entra/commands.js +1 -0
  14. package/dist/m365/external/commands/connection/connection-doctor.js +10 -24
  15. package/dist/m365/flow/commands/flow-list.js +23 -24
  16. package/dist/m365/graph/commands/subscription/subscription-add.js +4 -2
  17. package/dist/m365/spe/ContainerTypeProperties.js +2 -0
  18. package/dist/m365/spe/commands/containertype/containertype-list.js +49 -0
  19. package/dist/m365/spe/commands.js +2 -1
  20. package/dist/m365/spfx/commands/project/base-project-command.js +36 -126
  21. package/dist/m365/spo/commands/applicationcustomizer/applicationcustomizer-get.js +16 -21
  22. package/dist/m365/spo/commands/cdn/cdn-get.js +12 -15
  23. package/dist/m365/spo/commands/cdn/cdn-set.js +6 -4
  24. package/dist/m365/spo/commands/commandset/commandset-get.js +31 -17
  25. package/dist/m365/spo/commands/contenttype/contenttype-field-list.js +124 -0
  26. package/dist/m365/spo/commands/field/field-list.js +1 -1
  27. package/dist/m365/spo/commands/group/group-member-add.js +103 -99
  28. package/dist/m365/spo/commands/page/page-clientsidewebpart-add.js +2 -3
  29. package/dist/m365/spo/commands/page/page-text-add.js +2 -3
  30. package/dist/m365/spo/commands/spo-search.js +3 -4
  31. package/dist/m365/spo/commands/tenant/tenant-applicationcustomizer-get.js +19 -5
  32. package/dist/m365/spo/commands/tenant/tenant-commandset-get.js +20 -6
  33. package/dist/m365/spo/commands.js +1 -0
  34. package/dist/m365/teams/commands/meeting/meeting-attendancereport-get.js +119 -0
  35. package/dist/m365/teams/commands/message/message-remove.js +112 -0
  36. package/dist/m365/teams/commands.js +2 -0
  37. package/dist/m365/viva/commands/engage/engage-community-add.js +166 -0
  38. package/dist/m365/viva/commands.js +1 -0
  39. package/dist/utils/formatting.js +30 -1
  40. package/dist/utils/teams.js +49 -0
  41. package/dist/utils/validation.js +19 -0
  42. package/dist/utils/zod.js +124 -0
  43. package/docs/docs/cmd/entra/m365group/m365group-set.mdx +37 -7
  44. package/docs/docs/cmd/entra/multitenant/multitenant-get.mdx +94 -0
  45. package/docs/docs/cmd/external/connection/connection-doctor.mdx +9 -9
  46. package/docs/docs/cmd/flow/flow-list.mdx +114 -56
  47. package/docs/docs/cmd/graph/subscription/subscription-add.mdx +18 -0
  48. package/docs/docs/cmd/spe/containertype/containertype-list.mdx +131 -0
  49. package/docs/docs/cmd/spo/applicationcustomizer/applicationcustomizer-get.mdx +85 -36
  50. package/docs/docs/cmd/spo/applicationcustomizer/applicationcustomizer-list.mdx +18 -24
  51. package/docs/docs/cmd/spo/cdn/cdn-set.mdx +3 -3
  52. package/docs/docs/cmd/spo/commandset/commandset-get.mdx +75 -24
  53. package/docs/docs/cmd/spo/commandset/commandset-list.mdx +26 -32
  54. package/docs/docs/cmd/spo/contenttype/contenttype-field-list.mdx +172 -0
  55. package/docs/docs/cmd/spo/contenttype/contenttype-list.mdx +3 -3
  56. package/docs/docs/cmd/spo/field/field-list.mdx +3 -3
  57. package/docs/docs/cmd/spo/group/group-member-add.mdx +34 -27
  58. package/docs/docs/cmd/spo/tenant/tenant-applicationcustomizer-get.mdx +79 -30
  59. package/docs/docs/cmd/spo/tenant/tenant-applicationcustomizer-list.mdx +20 -19
  60. package/docs/docs/cmd/spo/tenant/tenant-commandset-get.mdx +84 -38
  61. package/docs/docs/cmd/spo/tenant/tenant-commandset-list.mdx +20 -19
  62. package/docs/docs/cmd/teams/meeting/meeting-attendancereport-get.mdx +138 -0
  63. package/docs/docs/cmd/teams/meeting/meeting-list.mdx +7 -3
  64. package/docs/docs/cmd/teams/message/message-remove.mdx +63 -0
  65. package/docs/docs/cmd/viva/engage/engage-community-add.mdx +168 -0
  66. package/npm-shrinkwrap.json +588 -1022
  67. package/package.json +7 -3
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
  }
@@ -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);
@@ -410,8 +431,34 @@ class Command {
410
431
  return '';
411
432
  }
412
433
  getTelemetryProperties(args) {
413
- this.telemetry.forEach(t => t(args));
414
- return this.telemetryProperties;
434
+ if (this.schema) {
435
+ const telemetryProperties = {};
436
+ this.optionsInfo.forEach(o => {
437
+ if (o.required) {
438
+ return;
439
+ }
440
+ if (typeof args.options[o.name] === 'undefined') {
441
+ return;
442
+ }
443
+ switch (o.type) {
444
+ case 'string':
445
+ telemetryProperties[o.name] = o.autocomplete ? args.options[o.name] : typeof args.options[o.name] !== 'undefined';
446
+ break;
447
+ case 'boolean':
448
+ telemetryProperties[o.name] = args.options[o.name];
449
+ break;
450
+ case 'number':
451
+ telemetryProperties[o.name] = typeof args.options[o.name] !== 'undefined';
452
+ break;
453
+ }
454
+ ;
455
+ });
456
+ return telemetryProperties;
457
+ }
458
+ else {
459
+ this.telemetry.forEach(t => t(args));
460
+ return this.telemetryProperties;
461
+ }
415
462
  }
416
463
  async getTextOutput(logStatement) {
417
464
  // 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
@@ -68,7 +66,7 @@ async function execute(rawArgs) {
68
66
  rawArgs.shift();
69
67
  }
70
68
  // parse args to see if a command has been specified
71
- const parsedArgs = minimist(rawArgs);
69
+ const parsedArgs = yargs(rawArgs);
72
70
  // load command
73
71
  await cli.loadCommandFromArgs(parsedArgs._);
74
72
  if (cli.commandToExecute) {
@@ -81,8 +79,7 @@ async function execute(rawArgs) {
81
79
  };
82
80
  }
83
81
  catch (e) {
84
- const optionsWithoutShorts = removeShortOptions({ options: parsedArgs });
85
- return cli.closeWithError(e.message, optionsWithoutShorts, false);
82
+ return cli.closeWithError(e.message, { options: parsedArgs }, false);
86
83
  }
87
84
  }
88
85
  else {
@@ -130,18 +127,30 @@ async function execute(rawArgs) {
130
127
  if (cli.optionsFromArgs.options.output === undefined) {
131
128
  cli.optionsFromArgs.options.output = cli.getSettingWithDefaultValue(settingsNames.output, 'json');
132
129
  }
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);
130
+ let finalArgs = cli.optionsFromArgs.options;
131
+ if (cli.commandToExecute?.command.schema) {
132
+ const startValidation = process.hrtime.bigint();
133
+ const result = cli.commandToExecute.command.getSchemaToParse().safeParse(cli.optionsFromArgs.options);
134
+ const endValidation = process.hrtime.bigint();
135
+ timings.validation.push(Number(endValidation - startValidation));
136
+ if (!result.success) {
137
+ return cli.closeWithError(result.error, cli.optionsFromArgs, true);
138
+ }
139
+ finalArgs = result.data;
140
+ }
141
+ else {
142
+ const startValidation = process.hrtime.bigint();
143
+ const validationResult = await cli.commandToExecute.command.validate(cli.optionsFromArgs, cli.commandToExecute);
144
+ const endValidation = process.hrtime.bigint();
145
+ timings.validation.push(Number(endValidation - startValidation));
146
+ if (validationResult !== true) {
147
+ return cli.closeWithError(validationResult, cli.optionsFromArgs, true);
148
+ }
139
149
  }
140
- cli.optionsFromArgs = removeShortOptions(cli.optionsFromArgs);
141
150
  const end = process.hrtime.bigint();
142
151
  timings.core.push(Number(end - start));
143
152
  try {
144
- await cli.executeCommand(cli.commandToExecute.command, cli.optionsFromArgs);
153
+ await cli.executeCommand(cli.commandToExecute.command, { options: finalArgs });
145
154
  const endTotal = process.hrtime.bigint();
146
155
  timings.total.push(Number(endTotal - start));
147
156
  await printTimings(rawArgs);
@@ -190,12 +199,6 @@ async function executeCommand(command, args) {
190
199
  // the command to execute
191
200
  const parentCommandName = cli.currentCommandName;
192
201
  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
202
  const startCommand = process.hrtime.bigint();
200
203
  try {
201
204
  await command.action(logger, args);
@@ -207,10 +210,6 @@ async function executeCommand(command, args) {
207
210
  finally {
208
211
  // restore the original command name
209
212
  cli.currentCommandName = parentCommandName;
210
- /* c8 ignore next 3 */
211
- if (cli.spinner.isSpinning) {
212
- cli.spinner.stop();
213
- }
214
213
  const endCommand = process.hrtime.bigint();
215
214
  timings.command.push(Number(endCommand - startCommand));
216
215
  }
@@ -361,12 +360,14 @@ async function loadCommandFromFile(commandFileUrl) {
361
360
  catch { }
362
361
  }
363
362
  function getCommandInfo(command, filePath = '', helpFilePath = '') {
363
+ const options = command.schema ? zod.schemaToOptions(command.schema) : getCommandOptions(command);
364
+ command.optionsInfo = options;
364
365
  return {
365
366
  aliases: command.alias(),
366
367
  name: command.name,
367
368
  description: command.description,
368
369
  command: command,
369
- options: getCommandOptions(command),
370
+ options,
370
371
  defaultProperties: command.defaultProperties(),
371
372
  file: filePath,
372
373
  help: helpFilePath
@@ -401,36 +402,47 @@ function getCommandOptions(command) {
401
402
  return options;
402
403
  }
403
404
  function getCommandOptionsFromArgs(args, commandInfo) {
404
- const minimistOptions = {
405
- alias: {}
405
+ const yargsOptions = {
406
+ alias: {},
407
+ configuration: {
408
+ "parse-numbers": false,
409
+ "strip-aliased": true,
410
+ "strip-dashed": true
411
+ }
406
412
  };
407
413
  let argsToParse = args;
408
414
  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 = {};
415
+ if (commandInfo.command.schema) {
416
+ yargsOptions.string = commandInfo.options.filter(o => o.type === 'string').map(o => o.name);
417
+ yargsOptions.boolean = commandInfo.options.filter(o => o.type === 'boolean').map(o => o.name);
418
+ yargsOptions.number = commandInfo.options.filter(o => o.type === 'number').map(o => o.name);
419
+ argsToParse = getRewrittenArgs(args, yargsOptions.boolean);
420
+ }
421
+ else {
422
+ const commandTypes = commandInfo.command.types;
423
+ if (commandTypes) {
424
+ yargsOptions.string = commandTypes.string;
425
+ // minimist will parse unused boolean options to 'false' (unused options => options that are not included in the args)
426
+ // But in the CLI booleans are nullable. They can can be true, false or undefined.
427
+ // For this reason we only pass boolean types that are actually used as arg.
428
+ yargsOptions.boolean = commandTypes.boolean.filter(optionName => args.some(arg => `--${optionName}` === arg || `-${optionName}` === arg));
429
+ }
430
+ argsToParse = getRewrittenArgs(args, commandTypes.boolean);
431
+ }
418
432
  commandInfo.options.forEach(option => {
419
433
  if (option.short && option.long) {
420
- minimistOptions.alias[option.short] = option.long;
434
+ yargsOptions.alias[option.long] = option.short;
421
435
  }
422
436
  });
423
- argsToParse = getRewrittenArgs(args, commandTypes);
424
437
  }
425
- return minimist(argsToParse, minimistOptions);
438
+ return yargs(argsToParse, yargsOptions);
426
439
  }
427
440
  /**
428
441
  * Rewrites arguments (if necessary) before passing them into minimist.
429
442
  * Currently only boolean values are checked and fixed.
430
443
  * Args are only checked and rewritten if the option has been added to the 'types.boolean' array.
431
444
  */
432
- function getRewrittenArgs(args, commandTypes) {
433
- const booleanTypes = commandTypes.boolean;
445
+ function getRewrittenArgs(args, booleanTypes) {
434
446
  if (booleanTypes.length === 0) {
435
447
  return args;
436
448
  }
@@ -736,6 +748,9 @@ async function closeWithError(error, args, showHelpIfEnabled = false) {
736
748
  return process.exit(exitCode);
737
749
  }
738
750
  let errorMessage = error instanceof CommandError ? error.message : error;
751
+ if (error instanceof ZodError) {
752
+ errorMessage = error.errors.map(e => `${e.path}: ${e.message}`).join(os.EOL);
753
+ }
739
754
  if ((!args.options.output || args.options.output === 'json') &&
740
755
  !cli.getSettingWithDefaultValue(settingsNames.printErrorsAsPlainText, true)) {
741
756
  errorMessage = JSON.stringify({ error: errorMessage });
@@ -758,29 +773,14 @@ async function closeWithError(error, args, showHelpIfEnabled = false) {
758
773
  /* c8 ignore next */
759
774
  }
760
775
  function log(message, ...optionalParams) {
761
- const spinnerSpinning = cli.spinner.isSpinning;
762
- /* c8 ignore next 3 */
763
- if (spinnerSpinning) {
764
- cli.spinner.stop();
765
- }
766
776
  if (message) {
767
777
  console.log(message, ...optionalParams);
768
778
  }
769
779
  else {
770
780
  console.log();
771
781
  }
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
782
  }
778
783
  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
784
  const errorOutput = cli.getSettingWithDefaultValue(settingsNames.errorOutput, 'stderr');
785
785
  if (errorOutput === 'stdout') {
786
786
  console.log(message, ...optionalParams);
@@ -788,40 +788,15 @@ async function error(message, ...optionalParams) {
788
788
  else {
789
789
  console.error(message, ...optionalParams);
790
790
  }
791
- // Restart the spinner if it was running before the log
792
- /* c8 ignore next 3 */
793
- if (spinnerSpinning) {
794
- cli.spinner.start();
795
- }
796
791
  }
797
792
  async function promptForSelection(config) {
798
- const spinnerSpinning = cli.spinner.isSpinning;
799
- /* c8 ignore next 3 */
800
- if (spinnerSpinning) {
801
- cli.spinner.stop();
802
- }
803
793
  const answer = await prompt.forSelection(config);
804
794
  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
795
  return answer;
811
796
  }
812
797
  async function promptForConfirmation(config) {
813
- const spinnerSpinning = cli.spinner.isSpinning;
814
- /* c8 ignore next 3 */
815
- if (spinnerSpinning) {
816
- cli.spinner.stop();
817
- }
818
798
  const answer = await prompt.forConfirmation(config);
819
799
  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
800
  return answer;
826
801
  }
827
802
  async function handleMultipleResultsFound(message, values) {
@@ -834,13 +809,6 @@ async function handleMultipleResultsFound(message, values) {
834
809
  const response = await cli.promptForSelection({ message: `Please choose one:`, choices });
835
810
  return values[response];
836
811
  }
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
812
  function loadOptionValuesFromFiles(args) {
845
813
  const optionNames = Object.getOwnPropertyNames(args.options);
846
814
  optionNames.forEach(option => {
@@ -885,14 +853,6 @@ export const cli = {
885
853
  printAvailableCommands,
886
854
  promptForConfirmation,
887
855
  promptForSelection,
888
- 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
856
+ shouldTrimOutput
896
857
  };
897
- cli.spinner = ora(spinnerOptions);
898
858
  //# sourceMappingURL=cli.js.map
@@ -1,17 +1,30 @@
1
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
- };
6
- var _LoginCommand_instances, _a, _LoginCommand_initTelemetry, _LoginCommand_initOptions, _LoginCommand_initValidators;
7
1
  import fs from 'fs';
2
+ import { z } from 'zod';
8
3
  import auth, { AuthType, CloudType } from '../../Auth.js';
9
- import Command, { CommandError } from '../../Command.js';
4
+ import Command, { CommandError, globalOptionsZod } from '../../Command.js';
5
+ import { cli } from '../../cli/cli.js';
10
6
  import config from '../../config.js';
11
- import { misc } from '../../utils/misc.js';
12
- import commands from './commands.js';
13
7
  import { settingsNames } from '../../settingsNames.js';
14
- import { cli } from '../../cli/cli.js';
8
+ import { zod } from '../../utils/zod.js';
9
+ import commands from './commands.js';
10
+ const options = globalOptionsZod
11
+ .extend({
12
+ authType: zod.alias('t', z.enum(['certificate', 'deviceCode', 'password', 'identity', 'browser', 'secret']).optional()),
13
+ cloud: z.nativeEnum(CloudType).optional().default(CloudType.Public),
14
+ userName: zod.alias('u', z.string().optional()),
15
+ password: zod.alias('p', z.string().optional()),
16
+ certificateFile: zod.alias('c', z.string().optional()
17
+ .refine(filePath => !filePath || fs.existsSync(filePath), filePath => ({
18
+ message: `Certificate file ${filePath} does not exist`
19
+ }))),
20
+ certificateBase64Encoded: z.string().optional(),
21
+ thumbprint: z.string().optional(),
22
+ appId: z.string().optional(),
23
+ tenant: z.string().optional(),
24
+ secret: zod.alias('s', z.string().optional()),
25
+ connectionName: z.string().optional()
26
+ })
27
+ .strict();
15
28
  class LoginCommand extends Command {
16
29
  get name() {
17
30
  return commands.LOGIN;
@@ -19,12 +32,26 @@ class LoginCommand extends Command {
19
32
  get description() {
20
33
  return 'Log in to Microsoft 365';
21
34
  }
22
- constructor() {
23
- super();
24
- _LoginCommand_instances.add(this);
25
- __classPrivateFieldGet(this, _LoginCommand_instances, "m", _LoginCommand_initTelemetry).call(this);
26
- __classPrivateFieldGet(this, _LoginCommand_instances, "m", _LoginCommand_initOptions).call(this);
27
- __classPrivateFieldGet(this, _LoginCommand_instances, "m", _LoginCommand_initValidators).call(this);
35
+ get schema() {
36
+ return options;
37
+ }
38
+ getRefinedSchema(schema) {
39
+ return schema
40
+ .refine(options => options.authType !== 'password' || options.userName, {
41
+ message: 'Username is required when using password authentication'
42
+ })
43
+ .refine(options => options.authType !== 'password' || options.password, {
44
+ message: 'Password is required when using password authentication'
45
+ })
46
+ .refine(options => options.authType !== 'certificate' || !(options.certificateFile && options.certificateBase64Encoded), {
47
+ message: 'Specify either certificateFile or certificateBase64Encoded, but not both.'
48
+ })
49
+ .refine(options => options.authType !== 'certificate' || options.certificateFile || options.certificateBase64Encoded, {
50
+ message: 'Specify either certificateFile or certificateBase64Encoded'
51
+ })
52
+ .refine(options => options.authType !== 'secret' || options.secret, {
53
+ message: 'Secret is required when using secret authentication'
54
+ });
28
55
  }
29
56
  async commandAction(logger, args) {
30
57
  // disconnect before re-connecting
@@ -64,12 +91,7 @@ class LoginCommand extends Command {
64
91
  auth.connection.secret = args.options.secret;
65
92
  break;
66
93
  }
67
- if (args.options.cloud) {
68
- auth.connection.cloudType = CloudType[args.options.cloud];
69
- }
70
- else {
71
- auth.connection.cloudType = CloudType.Public;
72
- }
94
+ auth.connection.cloudType = args.options.cloud;
73
95
  try {
74
96
  await auth.ensureAccessToken(auth.defaultResource, logger, this.debug);
75
97
  auth.connection.active = true;
@@ -102,79 +124,5 @@ class LoginCommand extends Command {
102
124
  await this.commandAction(logger, args);
103
125
  }
104
126
  }
105
- _a = LoginCommand, _LoginCommand_instances = new WeakSet(), _LoginCommand_initTelemetry = function _LoginCommand_initTelemetry() {
106
- this.telemetry.push((args) => {
107
- Object.assign(this.telemetryProperties, {
108
- authType: args.options.authType || cli.getSettingWithDefaultValue(settingsNames.authType, 'deviceCode'),
109
- cloud: args.options.cloud ?? CloudType.Public
110
- });
111
- });
112
- }, _LoginCommand_initOptions = function _LoginCommand_initOptions() {
113
- this.options.unshift({
114
- option: '-t, --authType [authType]',
115
- autocomplete: _a.allowedAuthTypes
116
- }, {
117
- option: '-u, --userName [userName]'
118
- }, {
119
- option: '-p, --password [password]'
120
- }, {
121
- option: '-c, --certificateFile [certificateFile]'
122
- }, {
123
- option: '--certificateBase64Encoded [certificateBase64Encoded]'
124
- }, {
125
- option: '--thumbprint [thumbprint]'
126
- }, {
127
- option: '--appId [appId]'
128
- }, {
129
- option: '--tenant [tenant]'
130
- }, {
131
- option: '-s, --secret [secret]'
132
- }, {
133
- option: '--cloud [cloud]',
134
- autocomplete: misc.getEnums(CloudType)
135
- }, {
136
- option: '--connectionName [connectionName]'
137
- });
138
- }, _LoginCommand_initValidators = function _LoginCommand_initValidators() {
139
- this.validators.push(async (args) => {
140
- const authType = args.options.authType || cli.getSettingWithDefaultValue(settingsNames.authType, 'deviceCode');
141
- if (authType === 'password') {
142
- if (!args.options.userName) {
143
- return 'Required option userName missing';
144
- }
145
- if (!args.options.password) {
146
- return 'Required option password missing';
147
- }
148
- }
149
- if (authType === 'certificate') {
150
- if (args.options.certificateFile && args.options.certificateBase64Encoded) {
151
- return 'Specify either certificateFile or certificateBase64Encoded, but not both.';
152
- }
153
- if (!args.options.certificateFile && !args.options.certificateBase64Encoded) {
154
- return 'Specify either certificateFile or certificateBase64Encoded';
155
- }
156
- if (args.options.certificateFile) {
157
- if (!fs.existsSync(args.options.certificateFile)) {
158
- return `File '${args.options.certificateFile}' does not exist`;
159
- }
160
- }
161
- }
162
- if (authType &&
163
- _a.allowedAuthTypes.indexOf(authType) < 0) {
164
- return `'${authType}' is not a valid authentication type. Allowed authentication types are ${_a.allowedAuthTypes.join(', ')}`;
165
- }
166
- if (authType === 'secret') {
167
- if (!args.options.secret) {
168
- return 'Required option secret missing';
169
- }
170
- }
171
- if (args.options.cloud &&
172
- typeof CloudType[args.options.cloud] === 'undefined') {
173
- return `${args.options.cloud} is not a valid value for cloud. Valid options are ${misc.getEnums(CloudType).join(', ')}`;
174
- }
175
- return true;
176
- });
177
- };
178
- LoginCommand.allowedAuthTypes = ['certificate', 'deviceCode', 'password', 'identity', 'browser', 'secret'];
179
127
  export default new LoginCommand();
180
128
  //# sourceMappingURL=login.js.map