@pnp/cli-microsoft365 7.10.0-beta.ebb7426 → 7.11.0-beta.10b9b79

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 (64) hide show
  1. package/.eslintrc.cjs +5 -2
  2. package/allCommands.json +1 -1
  3. package/allCommandsFull.json +1 -1
  4. package/dist/Auth.js +1 -1
  5. package/dist/AuthServer.js +10 -10
  6. package/dist/Command.js +10 -10
  7. package/dist/chili/index.js +1 -1
  8. package/dist/cli/cli.js +11 -11
  9. package/dist/index.js +1 -1
  10. package/dist/m365/base/AnonymousCommand.js +1 -1
  11. package/dist/m365/base/DelegatedGraphCommand.js +2 -2
  12. package/dist/m365/base/PowerAppsCommand.js +2 -2
  13. package/dist/m365/base/PowerAutomateCommand.js +2 -2
  14. package/dist/m365/base/PowerBICommand.js +2 -2
  15. package/dist/m365/base/PowerPlatformCommand.js +2 -2
  16. package/dist/m365/base/VivaEngageCommand.js +2 -2
  17. package/dist/m365/cli/commands/cli-consent.js +1 -1
  18. package/dist/m365/commands/login.js +1 -1
  19. package/dist/m365/commands/logout.js +1 -1
  20. package/dist/m365/commands/status.js +1 -1
  21. package/dist/m365/connection/commands/connection-list.js +1 -1
  22. package/dist/m365/connection/commands/connection-remove.js +1 -1
  23. package/dist/m365/connection/commands/connection-set.js +1 -1
  24. package/dist/m365/connection/commands/connection-use.js +1 -1
  25. package/dist/m365/entra/commands/app/app-permission-add.js +21 -1
  26. package/dist/m365/entra/commands/app/app-permission-remove.js +17 -0
  27. package/dist/m365/entra/commands/m365group/m365group-add.js +1 -0
  28. package/dist/m365/entra/commands/m365group/m365group-user-list.js +1 -1
  29. package/dist/m365/external/commands/connection/connection-doctor.js +1 -1
  30. package/dist/m365/external/commands/connection/connection-schema-add.js +4 -4
  31. package/dist/m365/file/commands/file-copy.js +3 -3
  32. package/dist/m365/pa/commands/app/app-export.js +1 -1
  33. package/dist/m365/pa/commands/app/app-owner-set.js +1 -1
  34. package/dist/m365/pp/commands/solution/solution-publish.js +1 -1
  35. package/dist/m365/purview/commands/threatassessment/threatassessment-list.js +1 -1
  36. package/dist/m365/spfx/commands/project/project-azuredevops-pipeline-add.js +1 -1
  37. package/dist/m365/spfx/commands/project/project-externalize.js +1 -1
  38. package/dist/m365/spfx/commands/project/project-github-workflow-add.js +1 -1
  39. package/dist/m365/spfx/commands/spfx-doctor.js +4 -4
  40. package/dist/m365/spo/commands/commandset/commandset-get.js +1 -1
  41. package/dist/m365/spo/commands/file/file-retentionlabel-remove.js +1 -1
  42. package/dist/m365/spo/commands/group/group-member-add.js +2 -2
  43. package/dist/m365/spo/commands/group/group-member-remove.js +2 -2
  44. package/dist/m365/spo/commands/list/list-retentionlabel-ensure.js +1 -1
  45. package/dist/m365/spo/commands/listitem/listitem-batch-remove.js +1 -1
  46. package/dist/m365/spo/commands/listitem/listitem-retentionlabel-ensure.js +2 -2
  47. package/dist/m365/spo/commands/listitem/listitem-retentionlabel-remove.js +2 -2
  48. package/dist/m365/spo/commands/site/site-admin-list.js +144 -0
  49. package/dist/m365/spo/commands/site/site-commsite-enable.js +1 -1
  50. package/dist/m365/spo/commands/spo-search.js +1 -1
  51. package/dist/m365/spo/commands/tenant/tenant-applicationcustomizer-set.js +4 -4
  52. package/dist/m365/spo/commands/tenant/tenant-commandset-set.js +2 -2
  53. package/dist/m365/spo/commands/user/user-ensure.js +1 -1
  54. package/dist/m365/spo/commands.js +1 -0
  55. package/dist/m365/teams/commands/chat/chat-member-add.js +1 -1
  56. package/dist/m365/teams/commands/meeting/meeting-list.js +1 -1
  57. package/dist/m365/viva/commands/engage/engage-community-get.js +1 -1
  58. package/dist/request.js +13 -14
  59. package/dist/utils/spo.js +5 -5
  60. package/dist/utils/validation.js +6 -0
  61. package/docs/docs/cmd/entra/app/app-permission-remove.mdx +4 -4
  62. package/docs/docs/cmd/spo/site/site-admin-list.mdx +115 -0
  63. package/npm-shrinkwrap.json +802 -601
  64. package/package.json +12 -12
package/dist/Auth.js CHANGED
@@ -364,7 +364,7 @@ export class Auth {
364
364
  cli.spinner.start();
365
365
  }
366
366
  if (cli.getSettingWithDefaultValue(settingsNames.autoOpenLinksInBrowser, false)) {
367
- browserUtil.open(response.verificationUri);
367
+ await browserUtil.open(response.verificationUri);
368
368
  }
369
369
  if (cli.getSettingWithDefaultValue(settingsNames.copyDeviceCodeToClipboard, false)) {
370
370
  // _clipboardy is never set before hitting this line, but this check
@@ -16,23 +16,23 @@ export class AuthServer {
16
16
  this.resource = resource;
17
17
  this.httpServer = http.createServer(this.httpRequest).listen(0, this.httpListener);
18
18
  };
19
- this.httpListener = () => {
19
+ this.httpListener = async () => {
20
20
  const requestState = Math.random().toString(16).substr(2, 20);
21
21
  const address = this.httpServer.address();
22
22
  this.generatedServerUrl = `http://localhost:${address.port}`;
23
23
  const url = `${Auth.getEndpointForResource('https://login.microsoftonline.com', this.connection.cloudType)}/${this.connection.tenant}/oauth2/authorize?response_type=code&client_id=${this.connection.appId}&redirect_uri=${this.generatedServerUrl}&state=${requestState}&resource=${this.resource}&prompt=select_account`;
24
24
  if (this.debug) {
25
- this.logger.logToStderr('Redirect URL:');
26
- this.logger.logToStderr(url);
27
- this.logger.logToStderr('');
25
+ await this.logger.logToStderr('Redirect URL:');
26
+ await this.logger.logToStderr(url);
27
+ await this.logger.logToStderr('');
28
28
  }
29
29
  this.openUrl(url);
30
30
  };
31
- this.httpRequest = (request, response) => {
31
+ this.httpRequest = async (request, response) => {
32
32
  if (this.debug) {
33
- this.logger.logToStderr('Response:');
34
- this.logger.logToStderr(request.url);
35
- this.logger.logToStderr('');
33
+ await this.logger.logToStderr('Response:');
34
+ await this.logger.logToStderr(request.url);
35
+ await this.logger.logToStderr('');
36
36
  }
37
37
  // url.parse is deprecated but we can't move to URL, because it doesn't
38
38
  // support server-relative URLs
@@ -82,8 +82,8 @@ export class AuthServer {
82
82
  }
83
83
  openUrl(url) {
84
84
  browserUtil.open(url)
85
- .then(_ => {
86
- this.logger.logToStderr("To sign in, use the web browser that just has been opened. Please sign-in there.");
85
+ .then(async (_) => {
86
+ await this.logger.logToStderr("To sign in, use the web browser that just has been opened. Please sign-in there.");
87
87
  })
88
88
  .catch(_ => {
89
89
  const errorResponse = {
package/dist/Command.js CHANGED
@@ -88,7 +88,7 @@ class Command {
88
88
  }
89
89
  if (!prompted) {
90
90
  prompted = true;
91
- cli.error('🌶️ Provide values for the following parameters:');
91
+ await cli.error('🌶️ Provide values for the following parameters:');
92
92
  }
93
93
  const answer = optionInfo.autocomplete !== undefined
94
94
  ? await prompt.forSelection({ message: `${optionInfo.name}: `, choices: optionInfo.autocomplete.map((choice) => { return { name: choice, value: choice }; }) })
@@ -96,9 +96,9 @@ class Command {
96
96
  args.options[optionInfo.name] = answer;
97
97
  }
98
98
  if (prompted) {
99
- cli.error('');
99
+ await cli.error('');
100
100
  }
101
- this.processOptions(args.options);
101
+ await this.processOptions(args.options);
102
102
  return true;
103
103
  }
104
104
  async validateOptionSets(args, command) {
@@ -129,17 +129,17 @@ class Command {
129
129
  return true;
130
130
  }
131
131
  async promptForOptionSetNameAndValue(args, optionSet) {
132
- cli.error(`🌶️ Please specify one of the following options:`);
132
+ await cli.error(`🌶️ Please specify one of the following options:`);
133
133
  const selectedOptionName = await prompt.forSelection({ message: `Option to use:`, choices: optionSet.options.map((choice) => { return { name: choice, value: choice }; }) });
134
134
  const optionValue = await prompt.forInput({ message: `${selectedOptionName}:` });
135
135
  args.options[selectedOptionName] = optionValue;
136
- cli.error('');
136
+ await cli.error('');
137
137
  }
138
138
  async promptForSpecificOption(args, commonOptions) {
139
- cli.error(`🌶️ Multiple options for an option set specified. Please specify the correct option that you wish to use.`);
139
+ await cli.error(`🌶️ Multiple options for an option set specified. Please specify the correct option that you wish to use.`);
140
140
  const selectedOptionName = await prompt.forSelection({ message: `Option to use:`, choices: commonOptions.map((choice) => { return { name: choice, value: choice }; }) });
141
141
  commonOptions.filter(y => y !== selectedOptionName).map(optionName => args.options[optionName] = undefined);
142
- cli.error('');
142
+ await cli.error('');
143
143
  }
144
144
  async validateOutput(args) {
145
145
  if (args.options.output &&
@@ -179,7 +179,7 @@ class Command {
179
179
  catch (error) {
180
180
  throw new CommandError(error);
181
181
  }
182
- this.initAction(args, logger);
182
+ await this.initAction(args, logger);
183
183
  if (!auth.connection.active) {
184
184
  throw new CommandError('Log in to Microsoft 365 first');
185
185
  }
@@ -308,13 +308,13 @@ class Command {
308
308
  handleRejectedPromise(rawResponse) {
309
309
  this.handleError(rawResponse);
310
310
  }
311
- initAction(args, logger) {
311
+ async initAction(args, logger) {
312
312
  this.debug = args.options.debug || process.env.CLIMICROSOFT365_DEBUG === '1';
313
313
  this.verbose = this.debug || args.options.verbose || process.env.CLIMICROSOFT365_VERBOSE === '1';
314
314
  request.debug = this.debug;
315
315
  request.logger = logger;
316
316
  if (this.debug && auth.connection.identityName !== undefined) {
317
- logger.logToStderr(`Executing command as '${auth.connection.identityName}', appId: ${auth.connection.appId}, tenantId: ${auth.connection.identityTenantId}`);
317
+ await logger.logToStderr(`Executing command as '${auth.connection.identityName}', appId: ${auth.connection.appId}, tenantId: ${auth.connection.identityTenantId}`);
318
318
  }
319
319
  telemetry.trackEvent(this.getUsedCommandName(), this.getTelemetryProperties(args));
320
320
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { chili } from './chili.js';
3
3
  try {
4
- (async () => await chili.startConversation(process.argv.slice(2)))();
4
+ await (async () => await chili.startConversation(process.argv.slice(2)))();
5
5
  }
6
6
  catch (err) {
7
7
  console.error(`🛑 An error has occurred while searching documentation: ${err}`);
package/dist/cli/cli.js CHANGED
@@ -144,23 +144,23 @@ async function execute(rawArgs) {
144
144
  await cli.executeCommand(cli.commandToExecute.command, cli.optionsFromArgs);
145
145
  const endTotal = process.hrtime.bigint();
146
146
  timings.total.push(Number(endTotal - start));
147
- printTimings(rawArgs);
147
+ await printTimings(rawArgs);
148
148
  process.exit(0);
149
149
  }
150
150
  catch (err) {
151
151
  const endTotal = process.hrtime.bigint();
152
152
  timings.total.push(Number(endTotal - start));
153
- printTimings(rawArgs);
153
+ await printTimings(rawArgs);
154
154
  await cli.closeWithError(err, cli.optionsFromArgs);
155
155
  /* c8 ignore next */
156
156
  }
157
157
  }
158
- function printTimings(rawArgs) {
158
+ async function printTimings(rawArgs) {
159
159
  if (rawArgs.some(arg => arg === '--debug')) {
160
- cli.error('');
161
- cli.error('Timings:');
162
- Object.getOwnPropertyNames(timings).forEach(key => {
163
- cli.error(`${key}: ${timings[key].reduce((a, b) => a + b, 0) / 1e6}ms`);
160
+ await cli.error('');
161
+ await cli.error('Timings:');
162
+ Object.getOwnPropertyNames(timings).forEach(async (key) => {
163
+ await cli.error(`${key}: ${timings[key].reduce((a, b) => a + b, 0) / 1e6}ms`);
164
164
  });
165
165
  }
166
166
  }
@@ -179,7 +179,7 @@ async function executeCommand(command, args) {
179
179
  },
180
180
  logToStderr: async (message) => {
181
181
  if (args.options.output !== 'none') {
182
- cli.error(message);
182
+ await cli.error(message);
183
183
  }
184
184
  }
185
185
  };
@@ -801,7 +801,7 @@ async function promptForSelection(config) {
801
801
  cli.spinner.stop();
802
802
  }
803
803
  const answer = await prompt.forSelection(config);
804
- cli.error('');
804
+ await cli.error('');
805
805
  // Restart the spinner if it was running before the prompt
806
806
  /* c8 ignore next 3 */
807
807
  if (spinnerSpinning) {
@@ -816,7 +816,7 @@ async function promptForConfirmation(config) {
816
816
  cli.spinner.stop();
817
817
  }
818
818
  const answer = await prompt.forConfirmation(config);
819
- cli.error('');
819
+ await cli.error('');
820
820
  // Restart the spinner if it was running before the prompt
821
821
  /* c8 ignore next 3 */
822
822
  if (spinnerSpinning) {
@@ -829,7 +829,7 @@ async function handleMultipleResultsFound(message, values) {
829
829
  if (!prompt) {
830
830
  throw new Error(`${message} Found: ${Object.keys(values).join(', ')}.`);
831
831
  }
832
- cli.error(`🌶️ ${message} `);
832
+ await cli.error(`🌶️ ${message} `);
833
833
  const choices = Object.keys(values).map((choice) => { return { name: choice, value: choice }; });
834
834
  const response = await cli.promptForSelection({ message: `Please choose one:`, choices });
835
835
  return values[response];
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { cli } from './cli/cli.js';
3
3
  import { app } from './utils/app.js';
4
- (async () => {
4
+ await (async () => {
5
5
  // required to make console.log() in combination with piped output synchronous
6
6
  // on Windows/in PowerShell so that the output is not trimmed by calling
7
7
  // process.exit() after executing the command, while the output is still
@@ -1,7 +1,7 @@
1
1
  import Command from '../../Command.js';
2
2
  export default class AnonymousCommand extends Command {
3
3
  async action(logger, args) {
4
- this.initAction(args, logger);
4
+ await this.initAction(args, logger);
5
5
  await this.commandAction(logger, args);
6
6
  }
7
7
  }
@@ -5,8 +5,8 @@ import GraphCommand from './GraphCommand.js';
5
5
  * This command class is for delegated-only Graph commands.
6
6
  */
7
7
  export default class DelegatedGraphCommand extends GraphCommand {
8
- initAction(args, logger) {
9
- super.initAction(args, logger);
8
+ async initAction(args, logger) {
9
+ await super.initAction(args, logger);
10
10
  if (!auth.connection.active) {
11
11
  // we fail no login in the base command command class
12
12
  return;
@@ -5,8 +5,8 @@ export default class PowerAppsCommand extends Command {
5
5
  get resource() {
6
6
  return 'https://api.powerapps.com';
7
7
  }
8
- initAction(args, logger) {
9
- super.initAction(args, logger);
8
+ async initAction(args, logger) {
9
+ await super.initAction(args, logger);
10
10
  if (!auth.connection.active) {
11
11
  // we fail no login in the base command command class
12
12
  return;
@@ -5,8 +5,8 @@ export default class PowerAutomateCommand extends Command {
5
5
  get resource() {
6
6
  return 'https://api.flow.microsoft.com';
7
7
  }
8
- initAction(args, logger) {
9
- super.initAction(args, logger);
8
+ async initAction(args, logger) {
9
+ await super.initAction(args, logger);
10
10
  if (!auth.connection.active) {
11
11
  // we fail no login in the base command command class
12
12
  return;
@@ -5,8 +5,8 @@ export default class PowerBICommand extends Command {
5
5
  get resource() {
6
6
  return 'https://api.powerbi.com';
7
7
  }
8
- initAction(args, logger) {
9
- super.initAction(args, logger);
8
+ async initAction(args, logger) {
9
+ await super.initAction(args, logger);
10
10
  if (!auth.connection.active) {
11
11
  // we fail no login in the base command command class
12
12
  return;
@@ -5,8 +5,8 @@ export default class PowerPlatformCommand extends Command {
5
5
  get resource() {
6
6
  return 'https://api.bap.microsoft.com';
7
7
  }
8
- initAction(args, logger) {
9
- super.initAction(args, logger);
8
+ async initAction(args, logger) {
9
+ await super.initAction(args, logger);
10
10
  if (!auth.connection.active) {
11
11
  // we fail no login in the base command command class
12
12
  return;
@@ -5,8 +5,8 @@ export default class VivaEngageCommand extends Command {
5
5
  get resource() {
6
6
  return 'https://www.yammer.com/api';
7
7
  }
8
- initAction(args, logger) {
9
- super.initAction(args, logger);
8
+ async initAction(args, logger) {
9
+ await super.initAction(args, logger);
10
10
  if (!auth.connection.active) {
11
11
  // we fail no login in the base command command class
12
12
  return;
@@ -33,7 +33,7 @@ class CliConsentCommand extends AnonymousCommand {
33
33
  await logger.log(`To consent permissions for executing ${args.options.service} commands, navigate in your web browser to https://login.microsoftonline.com/${config.tenant}/oauth2/v2.0/authorize?client_id=${config.cliEntraAppId}&response_type=code&scope=${encodeURIComponent(scope)}`);
34
34
  }
35
35
  async action(logger, args) {
36
- this.initAction(args, logger);
36
+ await this.initAction(args, logger);
37
37
  await this.commandAction(logger, args);
38
38
  }
39
39
  }
@@ -98,7 +98,7 @@ class LoginCommand extends Command {
98
98
  catch (error) {
99
99
  throw new CommandError(error);
100
100
  }
101
- this.initAction(args, logger);
101
+ await this.initAction(args, logger);
102
102
  await this.commandAction(logger, args);
103
103
  }
104
104
  }
@@ -32,7 +32,7 @@ class LogoutCommand extends Command {
32
32
  catch (error) {
33
33
  throw new CommandError(error);
34
34
  }
35
- this.initAction(args, logger);
35
+ await this.initAction(args, logger);
36
36
  await this.commandAction(logger);
37
37
  }
38
38
  }
@@ -49,7 +49,7 @@ class StatusCommand extends Command {
49
49
  catch (error) {
50
50
  throw new CommandError(error);
51
51
  }
52
- this.initAction(args, logger);
52
+ await this.initAction(args, logger);
53
53
  await this.commandAction(logger);
54
54
  }
55
55
  }
@@ -39,7 +39,7 @@ class ConnectionListCommand extends Command {
39
39
  catch (error) {
40
40
  throw new CommandError(error);
41
41
  }
42
- this.initAction(args, logger);
42
+ await this.initAction(args, logger);
43
43
  await this.commandAction(logger);
44
44
  }
45
45
  }
@@ -46,7 +46,7 @@ class ConnectionRemoveCommand extends Command {
46
46
  catch (error) {
47
47
  throw new CommandError(error);
48
48
  }
49
- this.initAction(args, logger);
49
+ await this.initAction(args, logger);
50
50
  await this.commandAction(logger, args);
51
51
  }
52
52
  }
@@ -34,7 +34,7 @@ class ConnectionSetCommand extends Command {
34
34
  catch (error) {
35
35
  throw new CommandError(error);
36
36
  }
37
- this.initAction(args, logger);
37
+ await this.initAction(args, logger);
38
38
  await this.commandAction(logger, args);
39
39
  }
40
40
  }
@@ -38,7 +38,7 @@ class ConnectionUseCommand extends Command {
38
38
  catch (error) {
39
39
  throw new CommandError(error);
40
40
  }
41
- this.initAction(args, logger);
41
+ await this.initAction(args, logger);
42
42
  await this.commandAction(logger, args);
43
43
  }
44
44
  }
@@ -61,7 +61,10 @@ class EntraAppPermissionAddCommand extends GraphCommand {
61
61
  };
62
62
  await request.patch(addPermissionsRequestOptions);
63
63
  if (args.options.grantAdminConsent) {
64
- const appServicePrincipal = servicePrincipals.find(sp => sp.appId === appObject.appId);
64
+ let appServicePrincipal = servicePrincipals.find(sp => sp.appId === appObject.appId);
65
+ if (!appServicePrincipal) {
66
+ appServicePrincipal = await this.createServicePrincipal(appObject.appId, logger);
67
+ }
65
68
  await this.grantAdminConsent(appServicePrincipal, appPermissions, logger);
66
69
  }
67
70
  }
@@ -69,6 +72,23 @@ class EntraAppPermissionAddCommand extends GraphCommand {
69
72
  this.handleRejectedODataJsonPromise(err);
70
73
  }
71
74
  }
75
+ async createServicePrincipal(appId, logger) {
76
+ if (this.verbose) {
77
+ await logger.logToStderr(`Creating service principal for app ${appId}...`);
78
+ }
79
+ const requestOptions = {
80
+ url: `${this.resource}/v1.0/servicePrincipals`,
81
+ headers: {
82
+ accept: 'application/json;odata.metadata=none',
83
+ 'content-type': 'application/json;odata=nometadata'
84
+ },
85
+ data: {
86
+ appId
87
+ },
88
+ responseType: 'json'
89
+ };
90
+ return await request.post(requestOptions);
91
+ }
72
92
  async getAppObject(options) {
73
93
  let appNotFoundMessage = '';
74
94
  let apps = [];
@@ -49,6 +49,11 @@ class EntraAppPermissionRemoveCommand extends GraphCommand {
49
49
  const applicationPermissions = await this.getRequiredResourceAccessForApis(servicePrincipals, args.options.applicationPermissions, ScopeType.Role, appPermissions, logger);
50
50
  this.removePermissionsFromResourceArray(applicationPermissions, appObject.requiredResourceAccess);
51
51
  }
52
+ for (let i = 0; i < appObject.requiredResourceAccess.length; i++) {
53
+ if (appObject.requiredResourceAccess[i].resourceAccess?.length === 0) {
54
+ appObject.requiredResourceAccess.splice(i, 1);
55
+ }
56
+ }
52
57
  const removePermissionRequestOptions = {
53
58
  url: `${this.resource}/v1.0/applications/${appObject.id}`,
54
59
  headers: {
@@ -270,6 +275,18 @@ _EntraAppPermissionRemoveCommand_instances = new WeakSet(), _EntraAppPermissionR
270
275
  if (args.options.appObjectId && !validation.isValidGuid(args.options.appObjectId)) {
271
276
  return `${args.options.appObjectId} is not a valid GUID`;
272
277
  }
278
+ if (args.options.delegatedPermissions) {
279
+ const invalidPermissions = validation.isValidPermission(args.options.delegatedPermissions);
280
+ if (Array.isArray(invalidPermissions)) {
281
+ return `Delegated permission(s) ${invalidPermissions.join(', ')} are not fully-qualified`;
282
+ }
283
+ }
284
+ if (args.options.applicationPermissions) {
285
+ const invalidPermissions = validation.isValidPermission(args.options.applicationPermissions);
286
+ if (Array.isArray(invalidPermissions)) {
287
+ return `Application permission(s) ${invalidPermissions.join(', ')} are not fully-qualified`;
288
+ }
289
+ }
273
290
  return true;
274
291
  });
275
292
  }, _EntraAppPermissionRemoveCommand_initOptionSets = function _EntraAppPermissionRemoveCommand_initOptionSets() {
@@ -139,6 +139,7 @@ class EntraM365GroupAddCommand extends GraphCommand {
139
139
  const userArr = users.split(',').map(o => o.trim());
140
140
  let promises = [];
141
141
  let userIds = [];
142
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
142
143
  promises = userArr.map(user => {
143
144
  const requestOptions = {
144
145
  url: `${this.resource}/v1.0/users?$filter=userPrincipalName eq '${formatting.encodeQueryParameter(user)}'&$select=id,userPrincipalName`,
@@ -32,7 +32,7 @@ class EntraM365GroupUserListCommand extends GraphCommand {
32
32
  await this.showDeprecationWarning(logger, aadCommands.M365GROUP_USER_LIST, commands.M365GROUP_USER_LIST);
33
33
  try {
34
34
  if (args.options.role === 'Guest') {
35
- this.warn(logger, `Value 'Guest' for the option role is deprecated. Use --filter "userType eq 'Guest'" instead.`);
35
+ await this.warn(logger, `Value 'Guest' for the option role is deprecated. Use --filter "userType eq 'Guest'" instead.`);
36
36
  }
37
37
  const groupId = await this.getGroupId(args.options, logger);
38
38
  const isUnifiedGroup = await entraGroup.isUnifiedGroup(groupId);
@@ -112,7 +112,7 @@ class ExternalConnectionDoctorCommand extends GraphCommand {
112
112
  checks = checks.filter((check, index, self) => self.findIndex(c => c.id === check.id) === index);
113
113
  for (const check of checks) {
114
114
  if (this.debug) {
115
- logger.logToStderr(`Running check ${check.id}...`);
115
+ await logger.logToStderr(`Running check ${check.id}...`);
116
116
  }
117
117
  // don't show spinner if running tests
118
118
  /* c8 ignore next 3 */
@@ -39,19 +39,19 @@ class ExternalConnectionSchemaAddCommand extends GraphCommand {
39
39
  try {
40
40
  const res = await request.patch(requestOptions);
41
41
  const location = res.headers.location;
42
- logger.log(location);
42
+ await logger.log(location);
43
43
  if (!args.options.wait) {
44
44
  return;
45
45
  }
46
46
  let status;
47
47
  do {
48
48
  if (this.verbose) {
49
- logger.logToStderr(`Waiting 60 seconds...`);
49
+ await logger.logToStderr(`Waiting 60 seconds...`);
50
50
  }
51
51
  // waiting 60s before polling as recommended by Microsoft
52
52
  await new Promise(resolve => setTimeout(resolve, 60000));
53
53
  if (this.debug) {
54
- logger.logToStderr(`Checking schema operation status...`);
54
+ await logger.logToStderr(`Checking schema operation status...`);
55
55
  }
56
56
  const operation = await request.get({
57
57
  url: location,
@@ -62,7 +62,7 @@ class ExternalConnectionSchemaAddCommand extends GraphCommand {
62
62
  });
63
63
  status = operation.status;
64
64
  if (this.verbose) {
65
- logger.logToStderr(`Schema operation status: ${status}`);
65
+ await logger.logToStderr(`Schema operation status: ${status}`);
66
66
  }
67
67
  if (status === 'failed') {
68
68
  throw `Provisioning schema failed: ${operation.error?.message}`;
@@ -31,7 +31,7 @@ class FileCopyCommand extends GraphCommand {
31
31
  const sourcePath = this.getAbsoluteUrl(webUrl, sourceUrl);
32
32
  const destinationPath = this.getAbsoluteUrl(webUrl, targetUrl);
33
33
  if (this.verbose) {
34
- logger.logToStderr(`Copying file '${sourcePath}' to '${destinationPath}'...`);
34
+ await logger.logToStderr(`Copying file '${sourcePath}' to '${destinationPath}'...`);
35
35
  }
36
36
  const copyUrl = await this.getCopyUrl(args.options, sourcePath, logger);
37
37
  const { targetDriveId, targetItemId } = await this.getTargetDriveAndItemId(webUrl, targetUrl, logger, verbose);
@@ -83,7 +83,7 @@ class FileCopyCommand extends GraphCommand {
83
83
  }
84
84
  async getDocumentLibrary(siteId, folderUrl, folderUrlFromUser, logger) {
85
85
  if (this.verbose) {
86
- logger.logToStderr(`Getting document library...`);
86
+ await logger.logToStderr(`Getting document library...`);
87
87
  }
88
88
  const requestOptions = {
89
89
  url: `${this.resource}/v1.0/sites/${siteId}/drives?$select=webUrl,id`,
@@ -110,7 +110,7 @@ class FileCopyCommand extends GraphCommand {
110
110
  }
111
111
  async getStartingFolderId(documentLibrary, folderUrl, logger) {
112
112
  if (this.verbose) {
113
- logger.logToStderr(`Getting starting folder id...`);
113
+ await logger.logToStderr(`Getting starting folder id...`);
114
114
  }
115
115
  const documentLibraryRelativeFolderUrl = folderUrl.href.replace(new RegExp(`${documentLibrary.webUrl}`, 'i'), '').replace(/\/+$/, '');
116
116
  const requestOptions = {
@@ -128,7 +128,7 @@ class PaAppExportCommand extends PowerPlatformCommand {
128
128
  link = response.properties.packageLink.value;
129
129
  }
130
130
  else {
131
- setTimeout(this.pollingInterval);
131
+ await setTimeout(this.pollingInterval);
132
132
  }
133
133
  if (this.verbose) {
134
134
  await logger.logToStderr(`Current status of the get package link: ${status}`);
@@ -26,7 +26,7 @@ class PaAppOwnerSetCommand extends PowerAppsCommand {
26
26
  }
27
27
  async commandAction(logger, args) {
28
28
  if (this.verbose) {
29
- logger.logToStderr(`Setting new owner ${args.options.userId || args.options.userName} for Power Apps app ${args.options.appName}...`);
29
+ await logger.logToStderr(`Setting new owner ${args.options.userId || args.options.userName} for Power Apps app ${args.options.appName}...`);
30
30
  }
31
31
  try {
32
32
  const userId = await this.getUserId(args.options);
@@ -50,7 +50,7 @@ class PpSolutionPublishCommand extends PowerPlatformCommand {
50
50
  await request.post(requestOptions);
51
51
  }
52
52
  else {
53
- request.post(requestOptions);
53
+ void request.post(requestOptions);
54
54
  }
55
55
  }
56
56
  catch (err) {
@@ -26,7 +26,7 @@ class PurviewThreatAssessmentListCommand extends GraphCommand {
26
26
  }
27
27
  async commandAction(logger, args) {
28
28
  if (this.verbose) {
29
- logger.logToStderr('Retrieving a list of threat assessments');
29
+ await logger.logToStderr('Retrieving a list of threat assessments');
30
30
  }
31
31
  try {
32
32
  const filter = this.getFilterQuery(args.options);
@@ -37,7 +37,7 @@ class SpfxProjectAzureDevOpsPipelineAddCommand extends BaseProjectCommand {
37
37
  const packageJson = fs.readFileSync(solutionPackageJsonFile, 'utf-8');
38
38
  const solutionName = JSON.parse(packageJson).name;
39
39
  if (this.debug) {
40
- logger.logToStderr(`Adding Azure DevOps pipeline in the current SPFx project`);
40
+ await logger.logToStderr(`Adding Azure DevOps pipeline in the current SPFx project`);
41
41
  }
42
42
  try {
43
43
  this.updatePipeline(solutionName, pipeline, args.options);
@@ -81,7 +81,7 @@ class SpfxProjectExternalizeCommand extends BaseProjectCommand {
81
81
  this.allEditSuggestions.push(...rulesResults.map(x => x.suggestions).reduce((x, y) => [...x, ...y]));
82
82
  //removing duplicates
83
83
  this.allFindings = this.allFindings.filter((x, i) => this.allFindings.findIndex(y => y.key === x.key) === i);
84
- this.writeReport(this.allFindings, this.allEditSuggestions, logger, args.options);
84
+ await this.writeReport(this.allFindings, this.allEditSuggestions, logger, args.options);
85
85
  }
86
86
  catch (err) {
87
87
  throw new CommandError(err);
@@ -40,7 +40,7 @@ class SpfxProjectGithubWorkflowAddCommand extends BaseProjectCommand {
40
40
  const packageJson = fs.readFileSync(solutionPackageJsonFile, 'utf-8');
41
41
  const solutionName = JSON.parse(packageJson).name;
42
42
  if (this.debug) {
43
- logger.logToStderr(`Adding GitHub workflow in the current SPFx project`);
43
+ await logger.logToStderr(`Adding GitHub workflow in the current SPFx project`);
44
44
  }
45
45
  try {
46
46
  this.updateWorkflow(solutionName, workflow, args.options);
@@ -713,7 +713,7 @@ class SpfxDoctorCommand extends BaseProjectCommand {
713
713
  }
714
714
  async checkNodeVersion(prerequisites) {
715
715
  const nodeVersion = this.getNodeVersion();
716
- this.checkStatus('Node', nodeVersion, prerequisites.node);
716
+ await this.checkStatus('Node', nodeVersion, prerequisites.node);
717
717
  }
718
718
  async checkSharePointFrameworkVersion(spfxVersionRequested) {
719
719
  let spfxVersionDetected = await this.getSPFxVersionFromYoRcFile();
@@ -725,7 +725,7 @@ class SpfxDoctorCommand extends BaseProjectCommand {
725
725
  fix: `npm i -g @microsoft/generator-sharepoint@${spfxVersionRequested}`
726
726
  };
727
727
  if (spfxVersionDetected) {
728
- this.checkStatus(`SharePoint Framework`, spfxVersionDetected, versionCheck);
728
+ await this.checkStatus(`SharePoint Framework`, spfxVersionDetected, versionCheck);
729
729
  }
730
730
  else {
731
731
  const message = `SharePoint Framework v${spfxVersionRequested} not found`;
@@ -742,7 +742,7 @@ class SpfxDoctorCommand extends BaseProjectCommand {
742
742
  async checkYo(prerequisites) {
743
743
  const yoVersion = await this.getPackageVersion('yo', PackageSearchMode.GlobalOnly, HandlePromise.Continue);
744
744
  if (yoVersion) {
745
- this.checkStatus('yo', yoVersion, prerequisites.yo);
745
+ await this.checkStatus('yo', yoVersion, prerequisites.yo);
746
746
  }
747
747
  else {
748
748
  const message = 'yo not found';
@@ -758,7 +758,7 @@ class SpfxDoctorCommand extends BaseProjectCommand {
758
758
  async checkGulpCli(prerequisites) {
759
759
  const gulpCliVersion = await this.getPackageVersion('gulp-cli', PackageSearchMode.GlobalOnly, HandlePromise.Continue);
760
760
  if (gulpCliVersion) {
761
- this.checkStatus('gulp-cli', gulpCliVersion, prerequisites.gulpCli);
761
+ await this.checkStatus('gulp-cli', gulpCliVersion, prerequisites.gulpCli);
762
762
  }
763
763
  else {
764
764
  const message = 'gulp-cli not found';