@pnp/cli-microsoft365 7.2.0-beta.6775e3a → 7.2.0-beta.8577f52
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.
- package/allCommands.json +1 -0
- package/allCommandsFull.json +1 -0
- package/dist/Auth.js +1 -1
- package/dist/Command.js +13 -6
- package/dist/api.js +5 -7
- package/dist/cli/Cli.js +97 -119
- package/dist/cli/timings.js +9 -0
- package/dist/index.js +8 -14
- package/dist/m365/cli/commands/config/config-set.js +13 -0
- package/dist/m365/commands/login.js +12 -8
- package/dist/m365/flow/commands/environment/environment-list.js +6 -4
- package/dist/m365/spfx/commands/project/DeployWorkflow.js +4 -4
- package/dist/m365/spfx/commands/project/project-doctor/{doctor-1.18.1-rc.0.js → doctor-1.18.1.js} +1 -1
- package/dist/m365/spfx/commands/project/project-doctor/doctor-1.18.2.js +21 -0
- package/dist/m365/spfx/commands/project/project-doctor.js +6 -3
- package/dist/m365/spfx/commands/project/project-github-workflow-add.js +17 -0
- package/dist/m365/spfx/commands/project/project-upgrade/{upgrade-1.18.1-rc.0.js → upgrade-1.18.1.js} +26 -26
- package/dist/m365/spfx/commands/project/project-upgrade/upgrade-1.18.2.js +53 -0
- package/dist/m365/spfx/commands/project/project-upgrade.js +18 -17
- package/dist/m365/spfx/commands/spfx-doctor.js +16 -1
- package/dist/m365/spo/commands/file/file-retentionlabel-ensure.js +14 -23
- package/dist/m365/spo/commands/file/file-retentionlabel-remove.js +19 -27
- package/dist/m365/spo/commands/folder/folder-retentionlabel-ensure.js +9 -29
- package/dist/m365/spo/commands/folder/folder-retentionlabel-remove.js +9 -28
- package/dist/m365/spo/commands/list/list-retentionlabel-ensure.js +27 -37
- package/dist/m365/spo/commands/list/list-retentionlabel-remove.js +6 -19
- package/dist/m365/spo/commands/listitem/listitem-batch-add.js +5 -0
- package/dist/m365/spo/commands/listitem/listitem-retentionlabel-ensure.js +36 -37
- package/dist/m365/spo/commands/listitem/listitem-retentionlabel-remove.js +36 -32
- package/dist/m365/spo/commands/serviceprincipal/serviceprincipal-grant-revoke.js +49 -12
- package/dist/m365/spo/commands/site/site-add.js +45 -12
- package/dist/m365/spo/commands/sitescript/sitescript-get.js +8 -2
- package/dist/m365/spo/commands/tenant/tenant-recyclebinitem-restore.js +19 -2
- package/dist/m365/teams/commands/user/user-app-remove.js +18 -5
- package/dist/request.js +6 -0
- package/dist/settingsNames.js +2 -0
- package/dist/utils/prompt.js +5 -1
- package/dist/utils/spo.js +109 -0
- package/docs/docs/_clisettings.mdx +2 -0
- package/docs/docs/cmd/aad/approleassignment/approleassignment-add.mdx +1 -1
- package/docs/docs/cmd/aad/approleassignment/approleassignment-list.mdx +2 -2
- package/docs/docs/cmd/aad/approleassignment/approleassignment-remove.mdx +1 -1
- package/docs/docs/cmd/aad/oauth2grant/oauth2grant-add.mdx +1 -1
- package/docs/docs/cmd/aad/oauth2grant/oauth2grant-list.mdx +2 -2
- package/docs/docs/cmd/aad/oauth2grant/oauth2grant-remove.mdx +2 -2
- package/docs/docs/cmd/aad/oauth2grant/oauth2grant-set.mdx +2 -2
- package/docs/docs/cmd/aad/policy/policy-list.mdx +1 -1
- package/docs/docs/cmd/aad/siteclassification/siteclassification-disable.mdx +1 -1
- package/docs/docs/cmd/aad/siteclassification/siteclassification-enable.mdx +1 -1
- package/docs/docs/cmd/aad/siteclassification/siteclassification-get.mdx +1 -1
- package/docs/docs/cmd/aad/siteclassification/siteclassification-set.mdx +1 -1
- package/docs/docs/cmd/aad/sp/sp-add.mdx +2 -2
- package/docs/docs/cmd/aad/sp/sp-get.mdx +2 -2
- package/docs/docs/cmd/aad/user/user-add.mdx +3 -3
- package/docs/docs/cmd/aad/user/user-guest-add.mdx +1 -1
- package/docs/docs/cmd/aad/user/user-set.mdx +3 -3
- package/docs/docs/cmd/flow/run/run-cancel.mdx +3 -0
- package/docs/docs/cmd/graph/changelog/changelog-list.mdx +5 -5
- package/docs/docs/cmd/login.mdx +1 -1
- package/docs/docs/cmd/onenote/notebook/notebook-list.mdx +1 -1
- package/docs/docs/cmd/outlook/message/message-list.mdx +1 -1
- package/docs/docs/cmd/outlook/message/message-move.mdx +1 -1
- package/docs/docs/cmd/planner/bucket/bucket-add.mdx +1 -1
- package/docs/docs/cmd/planner/bucket/bucket-set.mdx +1 -1
- package/docs/docs/cmd/planner/plan/plan-set.mdx +3 -3
- package/docs/docs/cmd/planner/task/task-set.mdx +1 -1
- package/docs/docs/cmd/purview/auditlog/auditlog-list.mdx +3 -3
- package/docs/docs/cmd/purview/retentionevent/retentionevent-add.mdx +1 -1
- package/docs/docs/cmd/purview/retentionevent/retentionevent-get.mdx +1 -1
- package/docs/docs/cmd/purview/retentioneventtype/retentioneventtype-add.mdx +1 -1
- package/docs/docs/cmd/purview/retentioneventtype/retentioneventtype-get.mdx +1 -1
- package/docs/docs/cmd/purview/retentioneventtype/retentioneventtype-remove.mdx +1 -1
- package/docs/docs/cmd/purview/retentioneventtype/retentioneventtype-set.mdx +1 -1
- package/docs/docs/cmd/purview/retentionlabel/retentionlabel-add.mdx +1 -1
- package/docs/docs/cmd/purview/sensitivitylabel/sensitivitylabel-policysettings-list.mdx +4 -4
- package/docs/docs/cmd/spfx/project/project-upgrade.mdx +1 -1
- package/docs/docs/cmd/spo/app/app-add.mdx +1 -1
- package/docs/docs/cmd/spo/app/app-deploy.mdx +1 -1
- package/docs/docs/cmd/spo/app/app-get.mdx +1 -1
- package/docs/docs/cmd/spo/app/app-install.mdx +1 -1
- package/docs/docs/cmd/spo/app/app-list.mdx +1 -1
- package/docs/docs/cmd/spo/app/app-remove.mdx +1 -1
- package/docs/docs/cmd/spo/app/app-retract.mdx +1 -1
- package/docs/docs/cmd/spo/app/app-uninstall.mdx +1 -1
- package/docs/docs/cmd/spo/app/app-upgrade.mdx +1 -1
- package/docs/docs/cmd/spo/contenttype/contenttype-add.mdx +1 -1
- package/docs/docs/cmd/spo/contenttype/contenttype-set.mdx +1 -1
- package/docs/docs/cmd/spo/hidedefaultthemes/hidedefaultthemes-get.mdx +1 -1
- package/docs/docs/cmd/spo/hidedefaultthemes/hidedefaultthemes-set.mdx +1 -1
- package/docs/docs/cmd/spo/serviceprincipal/serviceprincipal-grant-revoke.mdx +10 -1
- package/docs/docs/cmd/spo/site/site-add.mdx +25 -4
- package/docs/docs/cmd/spo/site/site-appcatalog-add.mdx +1 -1
- package/docs/docs/cmd/spo/site/site-appcatalog-remove.mdx +1 -1
- package/docs/docs/cmd/spo/site/site-groupify.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-add.mdx +3 -3
- package/docs/docs/cmd/spo/sitedesign/sitedesign-apply.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-get.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-list.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-remove.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-rights-grant.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-rights-list.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-rights-revoke.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-run-list.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-run-status-get.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-set.mdx +3 -3
- package/docs/docs/cmd/spo/sitedesign/sitedesign-task-get.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-task-list.mdx +1 -1
- package/docs/docs/cmd/spo/sitedesign/sitedesign-task-remove.mdx +1 -1
- package/docs/docs/cmd/spo/sitescript/sitescript-add.mdx +1 -1
- package/docs/docs/cmd/spo/sitescript/sitescript-get.mdx +73 -3
- package/docs/docs/cmd/spo/sitescript/sitescript-list.mdx +1 -1
- package/docs/docs/cmd/spo/sitescript/sitescript-remove.mdx +1 -1
- package/docs/docs/cmd/spo/sitescript/sitescript-set.mdx +1 -1
- package/docs/docs/cmd/spo/storageentity/storageentity-get.mdx +1 -1
- package/docs/docs/cmd/spo/storageentity/storageentity-list.mdx +1 -1
- package/docs/docs/cmd/spo/storageentity/storageentity-remove.mdx +1 -1
- package/docs/docs/cmd/spo/storageentity/storageentity-set.mdx +1 -1
- package/docs/docs/cmd/spo/theme/theme-apply.mdx +1 -1
- package/docs/docs/cmd/spo/theme/theme-get.mdx +1 -1
- package/docs/docs/cmd/spo/theme/theme-list.mdx +1 -1
- package/docs/docs/cmd/spo/theme/theme-remove.mdx +1 -1
- package/docs/docs/cmd/spo/user/user-remove.mdx +1 -1
- package/docs/docs/cmd/spo/web/web-set.mdx +1 -1
- package/docs/docs/cmd/teams/channel/channel-remove.mdx +1 -1
- package/docs/docs/cmd/teams/meeting/meeting-get.mdx +1 -1
- package/docs/docs/cmd/teams/meeting/meeting-transcript-list.mdx +1 -1
- package/docs/docs/cmd/teams/report/report-pstncalls.mdx +1 -1
- package/docs/docs/cmd/teams/tab/tab-remove.mdx +1 -1
- package/docs/docs/cmd/teams/team/team-remove.mdx +1 -1
- package/docs/docs/cmd/teams/user/user-app-remove.mdx +11 -2
- package/docs/docs/cmd/tenant/serviceannouncement/serviceannouncement-healthissue-list.mdx +1 -1
- package/docs/docs/cmd/tenant/serviceannouncement/serviceannouncement-message-get.mdx +1 -1
- package/docs/docs/cmd/tenant/serviceannouncement/serviceannouncement-message-list.mdx +1 -1
- package/docs/docs/cmd/todo/task/task-set.mdx +1 -1
- package/npm-shrinkwrap.json +480 -516
- package/package.json +33 -32
package/dist/Auth.js
CHANGED
package/dist/Command.js
CHANGED
|
@@ -78,19 +78,22 @@ class Command {
|
|
|
78
78
|
const shouldPrompt = Cli.getInstance().getSettingWithDefaultValue(settingsNames.prompt, true);
|
|
79
79
|
let prompted = false;
|
|
80
80
|
for (let i = 0; i < command.options.length; i++) {
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
const optionInfo = command.options[i];
|
|
82
|
+
if (!optionInfo.required ||
|
|
83
|
+
typeof args.options[optionInfo.name] !== 'undefined') {
|
|
83
84
|
continue;
|
|
84
85
|
}
|
|
85
86
|
if (!shouldPrompt) {
|
|
86
|
-
return `Required option ${
|
|
87
|
+
return `Required option ${optionInfo.name} not specified`;
|
|
87
88
|
}
|
|
88
89
|
if (!prompted) {
|
|
89
90
|
prompted = true;
|
|
90
91
|
Cli.error('🌶️ Provide values for the following parameters:');
|
|
91
92
|
}
|
|
92
|
-
const answer =
|
|
93
|
-
|
|
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}: ` });
|
|
96
|
+
args.options[optionInfo.name] = answer;
|
|
94
97
|
}
|
|
95
98
|
if (prompted) {
|
|
96
99
|
Cli.error('');
|
|
@@ -457,7 +460,11 @@ class Command {
|
|
|
457
460
|
if (logStatement && logStatement.length > 0 && !options.query) {
|
|
458
461
|
logStatement.map(l => {
|
|
459
462
|
for (const x of Object.keys(l)) {
|
|
460
|
-
|
|
463
|
+
// Remove object-properties from the output
|
|
464
|
+
// Excludes null from the check, because null is an object in JavaScript.
|
|
465
|
+
// Properties with null values are not removed from the output,
|
|
466
|
+
// as this can cause missing columns
|
|
467
|
+
if (typeof l[x] === 'object' && l[x] !== null) {
|
|
461
468
|
delete l[x];
|
|
462
469
|
}
|
|
463
470
|
}
|
package/dist/api.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { Cli } from "./cli/Cli.js";
|
|
2
|
-
|
|
3
|
-
export function executeCommand(commandName, options, listener) {
|
|
2
|
+
export async function executeCommand(commandName, options, listener) {
|
|
4
3
|
const cli = Cli.getInstance();
|
|
5
|
-
cli.
|
|
6
|
-
cli.
|
|
7
|
-
cli.
|
|
8
|
-
if (cli.commands.length !== 1) {
|
|
4
|
+
cli.loadAllCommandsInfo();
|
|
5
|
+
await cli.loadCommandFromArgs(commandName.split(' '));
|
|
6
|
+
if (!cli.commandToExecute) {
|
|
9
7
|
return Promise.reject(`Command not found: ${commandName}`);
|
|
10
8
|
}
|
|
11
|
-
return Cli.executeCommandWithOutput(cli.
|
|
9
|
+
return Cli.executeCommandWithOutput(cli.commandToExecute.command, { options: options ?? {} }, listener);
|
|
12
10
|
}
|
|
13
11
|
//# sourceMappingURL=api.js.map
|
package/dist/cli/Cli.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import Configstore from 'configstore';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import minimist from 'minimist';
|
|
4
|
+
import { createRequire } from 'module';
|
|
4
5
|
import ora from 'ora';
|
|
5
6
|
import os from 'os';
|
|
6
7
|
import path from 'path';
|
|
7
|
-
import { pathToFileURL } from 'url';
|
|
8
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
8
9
|
import Command, { CommandError } from '../Command.js';
|
|
9
10
|
import config from '../config.js';
|
|
10
11
|
import request from '../request.js';
|
|
@@ -12,10 +13,12 @@ import { settingsNames } from '../settingsNames.js';
|
|
|
12
13
|
import { telemetry } from '../telemetry.js';
|
|
13
14
|
import { app } from '../utils/app.js';
|
|
14
15
|
import { formatting } from '../utils/formatting.js';
|
|
15
|
-
import { fsUtil } from '../utils/fsUtil.js';
|
|
16
16
|
import { md } from '../utils/md.js';
|
|
17
17
|
import { validation } from '../utils/validation.js';
|
|
18
18
|
import { prompt } from '../utils/prompt.js';
|
|
19
|
+
import { timings } from './timings.js';
|
|
20
|
+
const require = createRequire(import.meta.url);
|
|
21
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
19
22
|
export class Cli {
|
|
20
23
|
get config() {
|
|
21
24
|
if (!this._config) {
|
|
@@ -34,7 +37,6 @@ export class Cli {
|
|
|
34
37
|
}
|
|
35
38
|
constructor() {
|
|
36
39
|
this.commands = [];
|
|
37
|
-
this.commandsFolder = '';
|
|
38
40
|
const options = {
|
|
39
41
|
text: 'Running command...',
|
|
40
42
|
/* c8 ignore next 1 */
|
|
@@ -48,8 +50,11 @@ export class Cli {
|
|
|
48
50
|
}
|
|
49
51
|
return Cli.instance;
|
|
50
52
|
}
|
|
51
|
-
async execute(
|
|
52
|
-
|
|
53
|
+
async execute(rawArgs) {
|
|
54
|
+
const start = process.hrtime.bigint();
|
|
55
|
+
// for completion commands we also need information about commands' options
|
|
56
|
+
const loadAllCommandInfo = rawArgs.indexOf('completion') > -1;
|
|
57
|
+
this.loadAllCommandsInfo(loadAllCommandInfo);
|
|
53
58
|
// check if help for a specific command has been requested using the
|
|
54
59
|
// 'm365 help xyz' format. If so, remove 'help' from the array of words
|
|
55
60
|
// to use lazy loading commands but keep track of the fact that help should
|
|
@@ -59,22 +64,10 @@ export class Cli {
|
|
|
59
64
|
showHelp = true;
|
|
60
65
|
rawArgs.shift();
|
|
61
66
|
}
|
|
62
|
-
// parse args to see if a command has been specified
|
|
63
|
-
// rather than loading all commands
|
|
67
|
+
// parse args to see if a command has been specified
|
|
64
68
|
const parsedArgs = minimist(rawArgs);
|
|
65
|
-
// load
|
|
69
|
+
// load command
|
|
66
70
|
await this.loadCommandFromArgs(parsedArgs._);
|
|
67
|
-
if (this.currentCommandName) {
|
|
68
|
-
for (let i = 0; i < this.commands.length; i++) {
|
|
69
|
-
const command = this.commands[i];
|
|
70
|
-
if (command.name === this.currentCommandName ||
|
|
71
|
-
(command.aliases &&
|
|
72
|
-
command.aliases.indexOf(this.currentCommandName) > -1)) {
|
|
73
|
-
this.commandToExecute = command;
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
71
|
if (this.commandToExecute) {
|
|
79
72
|
// we have found a command to execute. Parse args again taking into
|
|
80
73
|
// account short and long options, option types and whether the command
|
|
@@ -90,6 +83,8 @@ export class Cli {
|
|
|
90
83
|
}
|
|
91
84
|
}
|
|
92
85
|
else {
|
|
86
|
+
// we need this to properly support displaying commands
|
|
87
|
+
// from the current group
|
|
93
88
|
this.optionsFromArgs = {
|
|
94
89
|
options: parsedArgs
|
|
95
90
|
};
|
|
@@ -113,26 +108,56 @@ export class Cli {
|
|
|
113
108
|
catch (e) {
|
|
114
109
|
return this.closeWithError(e, optionsWithoutShorts);
|
|
115
110
|
}
|
|
111
|
+
const startProcessing = process.hrtime.bigint();
|
|
116
112
|
try {
|
|
117
113
|
// process options before passing them on to validation stage
|
|
118
114
|
const contextCommandOptions = await this.loadOptionsFromContext(this.commandToExecute.options, optionsWithoutShorts.options.debug);
|
|
119
115
|
optionsWithoutShorts.options = { ...contextCommandOptions, ...optionsWithoutShorts.options };
|
|
120
116
|
await this.commandToExecute.command.processOptions(optionsWithoutShorts.options);
|
|
117
|
+
const endProcessing = process.hrtime.bigint();
|
|
118
|
+
timings.options.push(Number(endProcessing - startProcessing));
|
|
121
119
|
}
|
|
122
120
|
catch (e) {
|
|
121
|
+
const endProcessing = process.hrtime.bigint();
|
|
122
|
+
timings.options.push(Number(endProcessing - startProcessing));
|
|
123
123
|
return this.closeWithError(e.message, optionsWithoutShorts, false);
|
|
124
124
|
}
|
|
125
125
|
// if output not specified, set the configured output value (if any)
|
|
126
126
|
if (optionsWithoutShorts.options.output === undefined) {
|
|
127
127
|
optionsWithoutShorts.options.output = this.getSettingWithDefaultValue(settingsNames.output, 'json');
|
|
128
128
|
}
|
|
129
|
+
const startValidation = process.hrtime.bigint();
|
|
129
130
|
const validationResult = await this.commandToExecute.command.validate(optionsWithoutShorts, this.commandToExecute);
|
|
131
|
+
const endValidation = process.hrtime.bigint();
|
|
132
|
+
timings.validation.push(Number(endValidation - startValidation));
|
|
130
133
|
if (validationResult !== true) {
|
|
131
134
|
return this.closeWithError(validationResult, optionsWithoutShorts, true);
|
|
132
135
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
+
const end = process.hrtime.bigint();
|
|
137
|
+
timings.core.push(Number(end - start));
|
|
138
|
+
try {
|
|
139
|
+
await Cli.executeCommand(this.commandToExecute.command, optionsWithoutShorts);
|
|
140
|
+
const endTotal = process.hrtime.bigint();
|
|
141
|
+
timings.total.push(Number(endTotal - start));
|
|
142
|
+
this.printTimings(rawArgs);
|
|
143
|
+
process.exit(0);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
const endTotal = process.hrtime.bigint();
|
|
147
|
+
timings.total.push(Number(endTotal - start));
|
|
148
|
+
this.printTimings(rawArgs);
|
|
149
|
+
await this.closeWithError(err, optionsWithoutShorts);
|
|
150
|
+
/* c8 ignore next */
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
printTimings(rawArgs) {
|
|
154
|
+
if (rawArgs.some(arg => arg === '--debug')) {
|
|
155
|
+
Cli.error('');
|
|
156
|
+
Cli.error('Timings:');
|
|
157
|
+
Object.getOwnPropertyNames(timings).forEach(key => {
|
|
158
|
+
Cli.error(`${key}: ${timings[key].reduce((a, b) => a + b, 0) / 1e6}ms`);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
136
161
|
}
|
|
137
162
|
static async executeCommand(command, args) {
|
|
138
163
|
const logger = {
|
|
@@ -167,6 +192,7 @@ export class Cli {
|
|
|
167
192
|
if (showSpinner && typeof global.it === 'undefined') {
|
|
168
193
|
cli.spinner.start();
|
|
169
194
|
}
|
|
195
|
+
const startCommand = process.hrtime.bigint();
|
|
170
196
|
try {
|
|
171
197
|
await command.action(logger, args);
|
|
172
198
|
if (args.options.debug || args.options.verbose) {
|
|
@@ -181,6 +207,8 @@ export class Cli {
|
|
|
181
207
|
if (cli.spinner.isSpinning) {
|
|
182
208
|
cli.spinner.stop();
|
|
183
209
|
}
|
|
210
|
+
const endCommand = process.hrtime.bigint();
|
|
211
|
+
timings.command.push(Number(endCommand - startCommand));
|
|
184
212
|
}
|
|
185
213
|
}
|
|
186
214
|
static async executeCommandWithOutput(command, args, listener) {
|
|
@@ -248,55 +276,26 @@ export class Cli {
|
|
|
248
276
|
request.logger = currentLogger;
|
|
249
277
|
}
|
|
250
278
|
}
|
|
251
|
-
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
const file = pathToFileURL(filePath).toString();
|
|
255
|
-
if (file.indexOf(`/commands/`) > -1 &&
|
|
256
|
-
file.indexOf(`/assets/`) < 0 &&
|
|
257
|
-
file.endsWith('.js') &&
|
|
258
|
-
!file.endsWith('.spec.js')) {
|
|
259
|
-
try {
|
|
260
|
-
const command = await import(file);
|
|
261
|
-
if (command.default instanceof Command) {
|
|
262
|
-
this.loadCommand(command.default);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
catch (e) {
|
|
266
|
-
this.closeWithError(e, { options: {} });
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
}));
|
|
279
|
+
loadAllCommandsInfo(loadFull = false) {
|
|
280
|
+
const commandsInfoFileName = loadFull ? 'allCommandsFull.json' : 'allCommands.json';
|
|
281
|
+
this.commands = require(path.join(__dirname, '..', '..', commandsInfoFileName));
|
|
270
282
|
}
|
|
271
283
|
/**
|
|
272
284
|
* Loads command files into CLI based on the specified arguments.
|
|
273
285
|
*
|
|
274
286
|
* @param commandNameWords Array of words specified as args
|
|
275
|
-
|
|
287
|
+
*/
|
|
276
288
|
async loadCommandFromArgs(commandNameWords) {
|
|
277
|
-
this.currentCommandName = commandNameWords.join(' ');
|
|
278
289
|
if (commandNameWords.length === 0) {
|
|
279
|
-
await this.loadAllCommands();
|
|
280
290
|
return;
|
|
281
291
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
if (commandNameWords.length === 1) {
|
|
289
|
-
commandFilePath = path.join(this.commandsFolder, 'commands', `${commandNameWords[0]}.js`);
|
|
290
|
-
}
|
|
291
|
-
else {
|
|
292
|
-
if (commandNameWords.length === 2) {
|
|
293
|
-
commandFilePath = path.join(this.commandsFolder, commandNameWords[0], 'commands', `${commandNameWords.join('-')}.js`);
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
commandFilePath = path.join(this.commandsFolder, commandNameWords[0], 'commands', commandNameWords[1], commandNameWords.slice(1).join('-') + '.js');
|
|
297
|
-
}
|
|
292
|
+
this.currentCommandName = commandNameWords.join(' ');
|
|
293
|
+
const commandFilePath = this.commands
|
|
294
|
+
.find(c => c.name === this.currentCommandName ||
|
|
295
|
+
c.aliases?.find(a => a === this.currentCommandName))?.file ?? '';
|
|
296
|
+
if (commandFilePath) {
|
|
297
|
+
await this.loadCommandFromFile(commandFilePath);
|
|
298
298
|
}
|
|
299
|
-
await this.loadCommandFromFile(commandFilePath);
|
|
300
299
|
}
|
|
301
300
|
async loadOptionsFromContext(commandOptions, debug) {
|
|
302
301
|
const filePath = '.m365rc.json';
|
|
@@ -339,39 +338,37 @@ export class Cli {
|
|
|
339
338
|
* Loads command from the specified file into CLI. If can't find the file
|
|
340
339
|
* or the file doesn't contain a command, loads all available commands.
|
|
341
340
|
*
|
|
342
|
-
* @param
|
|
341
|
+
* @param commandFilePathUrl File path of the file with command to load
|
|
343
342
|
*/
|
|
344
|
-
async loadCommandFromFile(
|
|
345
|
-
|
|
346
|
-
|
|
343
|
+
async loadCommandFromFile(commandFileUrl) {
|
|
344
|
+
const commandsFolder = path.join(__dirname, '../m365');
|
|
345
|
+
const filePath = path.join(commandsFolder, commandFileUrl);
|
|
346
|
+
if (!fs.existsSync(filePath)) {
|
|
347
|
+
// reset command name
|
|
348
|
+
this.currentCommandName = undefined;
|
|
347
349
|
return;
|
|
348
350
|
}
|
|
349
351
|
try {
|
|
350
|
-
const
|
|
351
|
-
const command = await import(commandFileUrl);
|
|
352
|
+
const command = await import(pathToFileURL(filePath).toString());
|
|
352
353
|
if (command.default instanceof Command) {
|
|
353
|
-
this.
|
|
354
|
+
const commandInfo = this.commands.find(c => c.file === commandFileUrl);
|
|
355
|
+
this.commandToExecute = Cli.getCommandInfo(command.default, commandFileUrl, commandInfo?.help);
|
|
354
356
|
}
|
|
355
|
-
else {
|
|
356
|
-
await this.loadAllCommands();
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
catch {
|
|
360
|
-
await this.loadAllCommands();
|
|
361
357
|
}
|
|
358
|
+
catch { }
|
|
362
359
|
}
|
|
363
|
-
static getCommandInfo(command) {
|
|
360
|
+
static getCommandInfo(command, filePath = '', helpFilePath = '') {
|
|
364
361
|
return {
|
|
365
362
|
aliases: command.alias(),
|
|
366
363
|
name: command.name,
|
|
364
|
+
description: command.description,
|
|
367
365
|
command: command,
|
|
368
366
|
options: this.getCommandOptions(command),
|
|
369
|
-
defaultProperties: command.defaultProperties()
|
|
367
|
+
defaultProperties: command.defaultProperties(),
|
|
368
|
+
file: filePath,
|
|
369
|
+
help: helpFilePath
|
|
370
370
|
};
|
|
371
371
|
}
|
|
372
|
-
loadCommand(command) {
|
|
373
|
-
this.commands.push(Cli.getCommandInfo(command));
|
|
374
|
-
}
|
|
375
372
|
static getCommandOptions(command) {
|
|
376
373
|
const options = [];
|
|
377
374
|
command.options.forEach(option => {
|
|
@@ -508,7 +505,7 @@ export class Cli {
|
|
|
508
505
|
if (arrayType !== 'object') {
|
|
509
506
|
return logStatement.join(os.EOL);
|
|
510
507
|
}
|
|
511
|
-
// if output type has been set to 'text'
|
|
508
|
+
// if output type has been set to 'text', process the retrieved
|
|
512
509
|
// data so that returned objects contain only default properties specified
|
|
513
510
|
// on the current command. If there is no current command or the
|
|
514
511
|
// command doesn't specify default properties, return original data
|
|
@@ -568,58 +565,39 @@ export class Cli {
|
|
|
568
565
|
process.exit(exitCode);
|
|
569
566
|
}
|
|
570
567
|
printCommandHelp(helpMode) {
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
if (this.commandToExecute) {
|
|
574
|
-
commandNameWords = (this.commandToExecute.name).split(' ');
|
|
575
|
-
}
|
|
576
|
-
const pathChunks = [this.commandsFolder, '..', '..', 'docs', 'docs', 'cmd'];
|
|
577
|
-
if (commandNameWords.length === 1) {
|
|
578
|
-
pathChunks.push(`${commandNameWords[0]}.mdx`);
|
|
579
|
-
}
|
|
580
|
-
else {
|
|
581
|
-
if (commandNameWords.length === 2) {
|
|
582
|
-
pathChunks.push(commandNameWords[0], `${commandNameWords.join('-')}.mdx`);
|
|
583
|
-
}
|
|
584
|
-
else {
|
|
585
|
-
pathChunks.push(commandNameWords[0], commandNameWords[1], commandNameWords.slice(1).join('-') + '.mdx');
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
helpFilePath = path.join(...pathChunks);
|
|
568
|
+
const docsRootDir = path.join(__dirname, '..', '..', 'docs');
|
|
569
|
+
const helpFilePath = path.join(docsRootDir, 'docs', 'cmd', this.commandToExecute.help);
|
|
589
570
|
if (fs.existsSync(helpFilePath)) {
|
|
590
571
|
let helpContents = fs.readFileSync(helpFilePath, 'utf8');
|
|
591
572
|
helpContents = this.getHelpSection(helpMode, helpContents);
|
|
592
|
-
helpContents = md.md2plain(helpContents,
|
|
573
|
+
helpContents = md.md2plain(helpContents, docsRootDir);
|
|
593
574
|
Cli.log();
|
|
594
575
|
Cli.log(helpContents);
|
|
595
576
|
}
|
|
596
577
|
}
|
|
597
578
|
async getHelpMode(options) {
|
|
598
|
-
const h = options
|
|
599
|
-
|
|
579
|
+
const { h, help } = options;
|
|
580
|
+
if (!h && !help) {
|
|
581
|
+
return this.getSettingWithDefaultValue(settingsNames.helpMode, Cli.defaultHelpMode);
|
|
582
|
+
}
|
|
600
583
|
// user passed -h or --help, let's see if they passed a specific mode
|
|
601
584
|
// or requested the default
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
585
|
+
const helpMode = h ?? help;
|
|
586
|
+
if (typeof helpMode === 'boolean' || typeof helpMode !== 'string') {
|
|
587
|
+
// requested default mode or passed a number, let's use default
|
|
588
|
+
return this.getSettingWithDefaultValue(settingsNames.helpMode, Cli.defaultHelpMode);
|
|
589
|
+
}
|
|
590
|
+
else {
|
|
591
|
+
const lowerCaseHelpMode = helpMode.toLowerCase();
|
|
592
|
+
if (Cli.helpModes.indexOf(lowerCaseHelpMode) < 0) {
|
|
593
|
+
await Cli.getInstance().closeWithError(`Unknown help mode ${helpMode}. Allowed values are ${Cli.helpModes.join(', ')}`, { options }, false);
|
|
594
|
+
/* c8 ignore next 2 */
|
|
595
|
+
return ''; // noop
|
|
607
596
|
}
|
|
608
597
|
else {
|
|
609
|
-
|
|
610
|
-
if (Cli.helpModes.indexOf(lowerCaseHelpMode) < 0) {
|
|
611
|
-
await Cli.getInstance().closeWithError(`Unknown help mode ${helpMode}. Allowed values are ${Cli.helpModes.join(', ')}`, { options }, false);
|
|
612
|
-
/* c8 ignore next 2 */
|
|
613
|
-
return ''; // noop
|
|
614
|
-
}
|
|
615
|
-
else {
|
|
616
|
-
return lowerCaseHelpMode;
|
|
617
|
-
}
|
|
598
|
+
return lowerCaseHelpMode;
|
|
618
599
|
}
|
|
619
600
|
}
|
|
620
|
-
else {
|
|
621
|
-
return this.getSettingWithDefaultValue(settingsNames.helpMode, Cli.defaultHelpMode);
|
|
622
|
-
}
|
|
623
601
|
}
|
|
624
602
|
getHelpSection(helpMode, helpContents) {
|
|
625
603
|
if (helpMode === 'full') {
|
|
@@ -709,7 +687,7 @@ export class Cli {
|
|
|
709
687
|
Cli.log();
|
|
710
688
|
const sortedCommandNamesToPrint = Object.getOwnPropertyNames(commandsToPrint).sort();
|
|
711
689
|
sortedCommandNamesToPrint.forEach(commandName => {
|
|
712
|
-
Cli.log(` ${`${commandName} [options]`.padEnd(maxLength, ' ')} ${commandsToPrint[commandName].
|
|
690
|
+
Cli.log(` ${`${commandName} [options]`.padEnd(maxLength, ' ')} ${commandsToPrint[commandName].description}`);
|
|
713
691
|
});
|
|
714
692
|
}
|
|
715
693
|
const namesOfCommandGroupsToPrint = Object.keys(commandGroupsToPrint);
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import url from 'url';
|
|
5
2
|
import { Cli } from './cli/Cli.js';
|
|
6
3
|
import { telemetry } from './telemetry.js';
|
|
7
4
|
import { app } from './utils/app.js';
|
|
8
|
-
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
|
9
5
|
// required to make console.log() in combination with piped output synchronous
|
|
10
6
|
// on Windows/in PowerShell so that the output is not trimmed by calling
|
|
11
7
|
// process.exit() after executing the command, while the output is still
|
|
@@ -18,14 +14,12 @@ if (!process.env.CLIMICROSOFT365_NOUPDATE) {
|
|
|
18
14
|
updateNotifier.default({ pkg: app.packageJson() }).notify({ defer: false });
|
|
19
15
|
});
|
|
20
16
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
});
|
|
17
|
+
try {
|
|
18
|
+
const cli = Cli.getInstance();
|
|
19
|
+
cli.execute(process.argv.slice(2));
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
telemetry.trackException(e);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
31
25
|
//# sourceMappingURL=index.js.map
|
|
@@ -70,10 +70,23 @@ _a = CliConfigSetCommand, _CliConfigSetCommand_instances = new WeakSet(), _CliCo
|
|
|
70
70
|
allowedErrorOutputs.indexOf(args.options.value) === -1) {
|
|
71
71
|
return `${args.options.value} is not a valid value for the option ${args.options.key}. Allowed values: ${allowedErrorOutputs.join(', ')}`;
|
|
72
72
|
}
|
|
73
|
+
if (args.options.key === settingsNames.promptListPageSize &&
|
|
74
|
+
typeof args.options.value !== 'number') {
|
|
75
|
+
return `${args.options.value} is not a valid value for the option ${args.options.key}. The value has to be a number.`;
|
|
76
|
+
}
|
|
77
|
+
if (args.options.key === settingsNames.promptListPageSize &&
|
|
78
|
+
args.options.value <= 0) {
|
|
79
|
+
return `${args.options.value} is not a valid value for the option ${args.options.key}. The number has to be higher than 0.`;
|
|
80
|
+
}
|
|
73
81
|
if (args.options.key === settingsNames.helpMode &&
|
|
74
82
|
Cli.helpModes.indexOf(args.options.value) === -1) {
|
|
75
83
|
return `${args.options.value} is not a valid value for the option ${args.options.key}. Allowed values: ${Cli.helpModes.join(', ')}`;
|
|
76
84
|
}
|
|
85
|
+
const allowedAuthTypes = ['certificate', 'deviceCode', 'password', 'identity', 'browser', 'secret'];
|
|
86
|
+
if (args.options.key === settingsNames.authType &&
|
|
87
|
+
allowedAuthTypes.indexOf(args.options.value) === -1) {
|
|
88
|
+
return `${args.options.value} is not a valid value for the option ${args.options.key}. Allowed values: ${allowedAuthTypes.join(', ')}`;
|
|
89
|
+
}
|
|
77
90
|
return true;
|
|
78
91
|
});
|
|
79
92
|
};
|
|
@@ -11,6 +11,8 @@ import config from '../../config.js';
|
|
|
11
11
|
import { accessToken } from '../../utils/accessToken.js';
|
|
12
12
|
import { misc } from '../../utils/misc.js';
|
|
13
13
|
import commands from './commands.js';
|
|
14
|
+
import { settingsNames } from '../../settingsNames.js';
|
|
15
|
+
import { Cli } from '../../cli/Cli.js';
|
|
14
16
|
class LoginCommand extends Command {
|
|
15
17
|
get name() {
|
|
16
18
|
return commands.LOGIN;
|
|
@@ -35,9 +37,10 @@ class LoginCommand extends Command {
|
|
|
35
37
|
if (this.verbose) {
|
|
36
38
|
await logger.logToStderr(`Signing in to Microsoft 365...`);
|
|
37
39
|
}
|
|
40
|
+
const authType = args.options.authType || Cli.getInstance().getSettingWithDefaultValue(settingsNames.authType, 'deviceCode');
|
|
38
41
|
auth.service.appId = args.options.appId || config.cliAadAppId;
|
|
39
42
|
auth.service.tenant = args.options.tenant || config.tenant;
|
|
40
|
-
switch (
|
|
43
|
+
switch (authType) {
|
|
41
44
|
case 'password':
|
|
42
45
|
auth.service.authType = AuthType.Password;
|
|
43
46
|
auth.service.userName = args.options.userName;
|
|
@@ -126,7 +129,7 @@ class LoginCommand extends Command {
|
|
|
126
129
|
_a = LoginCommand, _LoginCommand_instances = new WeakSet(), _LoginCommand_initTelemetry = function _LoginCommand_initTelemetry() {
|
|
127
130
|
this.telemetry.push((args) => {
|
|
128
131
|
Object.assign(this.telemetryProperties, {
|
|
129
|
-
authType: args.options.authType || 'deviceCode',
|
|
132
|
+
authType: args.options.authType || Cli.getInstance().getSettingWithDefaultValue(settingsNames.authType, 'deviceCode'),
|
|
130
133
|
cloud: args.options.cloud ?? CloudType.Public
|
|
131
134
|
});
|
|
132
135
|
});
|
|
@@ -156,7 +159,8 @@ _a = LoginCommand, _LoginCommand_instances = new WeakSet(), _LoginCommand_initTe
|
|
|
156
159
|
});
|
|
157
160
|
}, _LoginCommand_initValidators = function _LoginCommand_initValidators() {
|
|
158
161
|
this.validators.push(async (args) => {
|
|
159
|
-
|
|
162
|
+
const authType = args.options.authType || Cli.getInstance().getSettingWithDefaultValue(settingsNames.authType, 'deviceCode');
|
|
163
|
+
if (authType === 'password') {
|
|
160
164
|
if (!args.options.userName) {
|
|
161
165
|
return 'Required option userName missing';
|
|
162
166
|
}
|
|
@@ -164,7 +168,7 @@ _a = LoginCommand, _LoginCommand_instances = new WeakSet(), _LoginCommand_initTe
|
|
|
164
168
|
return 'Required option password missing';
|
|
165
169
|
}
|
|
166
170
|
}
|
|
167
|
-
if (
|
|
171
|
+
if (authType === 'certificate') {
|
|
168
172
|
if (args.options.certificateFile && args.options.certificateBase64Encoded) {
|
|
169
173
|
return 'Specify either certificateFile or certificateBase64Encoded, but not both.';
|
|
170
174
|
}
|
|
@@ -177,11 +181,11 @@ _a = LoginCommand, _LoginCommand_instances = new WeakSet(), _LoginCommand_initTe
|
|
|
177
181
|
}
|
|
178
182
|
}
|
|
179
183
|
}
|
|
180
|
-
if (
|
|
181
|
-
_a.allowedAuthTypes.indexOf(
|
|
182
|
-
return `'${
|
|
184
|
+
if (authType &&
|
|
185
|
+
_a.allowedAuthTypes.indexOf(authType) < 0) {
|
|
186
|
+
return `'${authType}' is not a valid authentication type. Allowed authentication types are ${_a.allowedAuthTypes.join(', ')}`;
|
|
183
187
|
}
|
|
184
|
-
if (
|
|
188
|
+
if (authType === 'secret') {
|
|
185
189
|
if (!args.options.secret) {
|
|
186
190
|
return 'Required option secret missing';
|
|
187
191
|
}
|
|
@@ -17,10 +17,12 @@ class FlowEnvironmentListCommand extends AzmgmtCommand {
|
|
|
17
17
|
}
|
|
18
18
|
try {
|
|
19
19
|
const res = await odata.getAllItems(`${this.resource}providers/Microsoft.ProcessSimple/environments?api-version=2016-11-01`);
|
|
20
|
-
if (
|
|
21
|
-
|
|
22
|
-
e
|
|
23
|
-
|
|
20
|
+
if (res.length > 0) {
|
|
21
|
+
if (args.options.output !== 'json') {
|
|
22
|
+
res.forEach(e => {
|
|
23
|
+
e.displayName = e.properties.displayName;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
24
26
|
await logger.log(res);
|
|
25
27
|
}
|
|
26
28
|
}
|
|
@@ -16,10 +16,10 @@ export const workflow = {
|
|
|
16
16
|
uses: "actions/checkout@v3.5.3"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
name: "Use Node.js
|
|
19
|
+
name: "Use Node.js",
|
|
20
20
|
uses: "actions/setup-node@v3.7.0",
|
|
21
21
|
with: {
|
|
22
|
-
"node-version": "
|
|
22
|
+
"node-version": "18.x"
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
{
|
|
@@ -32,7 +32,7 @@ export const workflow = {
|
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
name: "CLI for Microsoft 365 Login",
|
|
35
|
-
uses: "pnp/action-cli-login@v2.2.
|
|
35
|
+
uses: "pnp/action-cli-login@v2.2.4",
|
|
36
36
|
with: {
|
|
37
37
|
"CERTIFICATE_ENCODED": "${{ secrets.CERTIFICATE_ENCODED }}",
|
|
38
38
|
"CERTIFICATE_PASSWORD": "${{ secrets.CERTIFICATE_PASSWORD }}",
|
|
@@ -41,7 +41,7 @@ export const workflow = {
|
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
name: "CLI for Microsoft 365 Deploy App",
|
|
44
|
-
uses: "pnp/action-cli-deploy@
|
|
44
|
+
uses: "pnp/action-cli-deploy@v4.0.0",
|
|
45
45
|
with: {
|
|
46
46
|
"APP_FILE_PATH": "sharepoint/solution/{{ solutionName }}.sppkg",
|
|
47
47
|
"SKIP_FEATURE_DEPLOYMENT": false,
|