@pnp/cli-microsoft365 7.8.0-beta.5ca5055 → 7.8.0-beta.a83837a
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 -1
- package/allCommandsFull.json +1 -1
- package/dist/cli/cli.js +5 -8
- package/dist/index.js +13 -12
- package/dist/m365/commands/setup.js +3 -3
- package/dist/m365/entra/commands/app/app-permission-add.js +25 -6
- package/dist/m365/entra/commands/app/app-permission-list.js +17 -5
- package/dist/m365/entra/commands/group/group-add.js +12 -14
- package/dist/m365/entra/commands/group/group-user-add.js +6 -7
- package/dist/m365/entra/commands/m365group/m365group-add.js +4 -2
- package/dist/m365/entra/commands/user/user-registrationdetails-list.js +6 -7
- package/dist/m365/outlook/commands/message/message-list.js +87 -17
- package/dist/m365/planner/commands/bucket/bucket-add.js +4 -7
- package/dist/m365/planner/commands/bucket/bucket-get.js +7 -30
- package/dist/m365/planner/commands/bucket/bucket-list.js +3 -6
- package/dist/m365/planner/commands/bucket/bucket-remove.js +8 -25
- package/dist/m365/planner/commands/bucket/bucket-set.js +12 -34
- package/dist/m365/planner/commands/plan/plan-add.js +17 -7
- package/dist/m365/planner/commands/plan/plan-get.js +12 -22
- package/dist/m365/planner/commands/plan/plan-list.js +1 -2
- package/dist/m365/planner/commands/plan/plan-remove.js +5 -3
- package/dist/m365/planner/commands/plan/plan-set.js +18 -10
- package/dist/m365/planner/commands/roster/roster-add.js +1 -2
- package/dist/m365/planner/commands/task/task-add.js +15 -21
- package/dist/m365/planner/commands/task/task-checklistitem-add.js +1 -1
- package/dist/m365/planner/commands/task/task-checklistitem-remove.js +1 -1
- package/dist/m365/planner/commands/task/task-get.js +5 -26
- package/dist/m365/planner/commands/task/task-list.js +11 -37
- package/dist/m365/planner/commands/task/task-reference-remove.js +1 -1
- package/dist/m365/planner/commands/task/task-remove.js +12 -29
- package/dist/m365/planner/commands/task/task-set.js +15 -21
- package/dist/m365/spo/commands/listitem/listitem-batch-remove.js +222 -0
- package/dist/m365/spo/commands/navigation/navigation-node-add.js +3 -2
- package/dist/m365/spo/commands/navigation/navigation-node-set.js +3 -2
- package/dist/m365/spo/commands/site/site-recyclebinitem-move.js +5 -2
- package/dist/m365/spo/commands/site/site-recyclebinitem-remove.js +3 -2
- package/dist/m365/spo/commands/site/site-remove.js +128 -149
- package/dist/m365/spo/commands/spo-set.js +6 -2
- package/dist/m365/spo/commands.js +1 -0
- package/dist/m365/teams/commands/meeting/meeting-add.js +3 -3
- package/dist/m365/teams/commands/team/team-add.js +22 -16
- package/dist/utils/planner.js +87 -8
- package/dist/utils/urlUtil.js +8 -0
- package/dist/utils/validation.js +8 -5
- package/docs/docs/cmd/entra/app/app-permission-add.mdx +7 -4
- package/docs/docs/cmd/entra/app/app-permission-list.mdx +14 -5
- package/docs/docs/cmd/entra/m365group/m365group-add.mdx +24 -24
- package/docs/docs/cmd/outlook/message/message-list.mdx +18 -6
- package/docs/docs/cmd/spo/listitem/listitem-batch-remove.mdx +70 -0
- package/docs/docs/cmd/spo/site/site-remove.mdx +9 -19
- package/package.json +1 -1
|
@@ -3,18 +3,17 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
3
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
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
|
-
var _SpoSiteRemoveCommand_instances, _SpoSiteRemoveCommand_initTelemetry, _SpoSiteRemoveCommand_initOptions, _SpoSiteRemoveCommand_initValidators;
|
|
7
|
-
import chalk from 'chalk';
|
|
6
|
+
var _SpoSiteRemoveCommand_instances, _SpoSiteRemoveCommand_initTelemetry, _SpoSiteRemoveCommand_initOptions, _SpoSiteRemoveCommand_initValidators, _SpoSiteRemoveCommand_initTypes;
|
|
8
7
|
import { cli } from '../../../../cli/cli.js';
|
|
9
|
-
import config from '../../../../config.js';
|
|
10
8
|
import request from '../../../../request.js';
|
|
11
|
-
import { entraGroup } from '../../../../utils/entraGroup.js';
|
|
12
9
|
import { formatting } from '../../../../utils/formatting.js';
|
|
13
|
-
import { spo } from '../../../../utils/spo.js';
|
|
14
10
|
import { validation } from '../../../../utils/validation.js';
|
|
15
11
|
import SpoCommand from '../../../base/SpoCommand.js';
|
|
16
12
|
import commands from '../../commands.js';
|
|
13
|
+
import { odata } from '../../../../utils/odata.js';
|
|
14
|
+
import { spo } from '../../../../utils/spo.js';
|
|
17
15
|
import { setTimeout } from 'timers/promises';
|
|
16
|
+
import { urlUtil } from '../../../../utils/urlUtil.js';
|
|
18
17
|
class SpoSiteRemoveCommand extends SpoCommand {
|
|
19
18
|
get name() {
|
|
20
19
|
return commands.SITE_REMOVE;
|
|
@@ -25,217 +24,180 @@ class SpoSiteRemoveCommand extends SpoCommand {
|
|
|
25
24
|
constructor() {
|
|
26
25
|
super();
|
|
27
26
|
_SpoSiteRemoveCommand_instances.add(this);
|
|
27
|
+
this.pollingInterval = 5000;
|
|
28
28
|
__classPrivateFieldGet(this, _SpoSiteRemoveCommand_instances, "m", _SpoSiteRemoveCommand_initTelemetry).call(this);
|
|
29
29
|
__classPrivateFieldGet(this, _SpoSiteRemoveCommand_instances, "m", _SpoSiteRemoveCommand_initOptions).call(this);
|
|
30
30
|
__classPrivateFieldGet(this, _SpoSiteRemoveCommand_instances, "m", _SpoSiteRemoveCommand_initValidators).call(this);
|
|
31
|
+
__classPrivateFieldGet(this, _SpoSiteRemoveCommand_instances, "m", _SpoSiteRemoveCommand_initTypes).call(this);
|
|
31
32
|
}
|
|
32
33
|
async commandAction(logger, args) {
|
|
34
|
+
if (args.options.wait) {
|
|
35
|
+
await this.warn(logger, `Option 'wait' is deprecated and will be removed in the next major release.`);
|
|
36
|
+
}
|
|
33
37
|
if (args.options.force) {
|
|
34
|
-
await this.removeSite(logger, args);
|
|
38
|
+
await this.removeSite(logger, args.options);
|
|
35
39
|
}
|
|
36
40
|
else {
|
|
37
|
-
const result = await cli.promptForConfirmation({ message: `Are you sure you want to remove the site ${args.options.url}?` });
|
|
41
|
+
const result = await cli.promptForConfirmation({ message: `Are you sure you want to remove the site '${args.options.url}'?` });
|
|
38
42
|
if (result) {
|
|
39
|
-
await this.removeSite(logger, args);
|
|
43
|
+
await this.removeSite(logger, args.options);
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
}
|
|
43
|
-
async removeSite(logger,
|
|
47
|
+
async removeSite(logger, options) {
|
|
44
48
|
try {
|
|
45
|
-
if (
|
|
46
|
-
await
|
|
49
|
+
if (this.verbose) {
|
|
50
|
+
await logger.logToStderr(`Removing site '${options.url}'...`);
|
|
47
51
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
this.spoAdminUrl = await spo.getSpoAdminUrl(logger, this.debug);
|
|
53
|
+
const siteUrl = urlUtil.removeTrailingSlashes(options.url);
|
|
54
|
+
const siteDetails = await this.getSiteDetails(logger, siteUrl);
|
|
55
|
+
const isGroupSite = siteDetails.GroupId && siteDetails.GroupId !== '00000000-0000-0000-0000-000000000000';
|
|
56
|
+
if (options.fromRecycleBin) {
|
|
57
|
+
if (!siteDetails.TimeDeleted) {
|
|
58
|
+
throw `Site is currently not in the recycle bin. Remove --fromRecycleBin if you want to remove it as active site.`;
|
|
55
59
|
}
|
|
56
|
-
|
|
57
|
-
if (this.
|
|
58
|
-
await logger.logToStderr(`
|
|
60
|
+
if (isGroupSite) {
|
|
61
|
+
if (this.verbose) {
|
|
62
|
+
await logger.logToStderr(`Checking if group '${siteDetails.GroupId}' is already permanently deleted from recycle bin.`);
|
|
59
63
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
await logger.logToStderr(chalk.yellow(`Entered site is a groupified site. Hence, the parameters 'skipRecycleBin' and 'wait' will not be applicable.`));
|
|
64
|
-
}
|
|
65
|
-
await this.deleteGroup(group.id, logger);
|
|
66
|
-
await this.deleteSite(args.options.url, args.options.wait, logger);
|
|
64
|
+
const isGroupInRecycleBin = await this.isGroupInEntraRecycleBin(logger, siteDetails.GroupId);
|
|
65
|
+
if (isGroupInRecycleBin) {
|
|
66
|
+
await this.removeGroupFromEntraRecycleBin(logger, siteDetails.GroupId);
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
68
|
+
}
|
|
69
|
+
await this.deleteSiteFromSharePointRecycleBin(logger, siteUrl);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
if (siteDetails.TimeDeleted) {
|
|
73
|
+
throw `Site is already in the recycle bin. Use --fromRecycleBin to permanently delete it.`;
|
|
74
|
+
}
|
|
75
|
+
if (isGroupSite) {
|
|
76
|
+
await this.deleteGroupifiedSite(logger, siteUrl);
|
|
77
|
+
if (options.skipRecycleBin) {
|
|
78
|
+
let isGroupInRecycleBin = await this.isGroupInEntraRecycleBin(logger, siteDetails.GroupId);
|
|
79
|
+
let amountOfPolls = 0;
|
|
80
|
+
while (!isGroupInRecycleBin && amountOfPolls < 20) {
|
|
81
|
+
await setTimeout(this.pollingInterval);
|
|
82
|
+
isGroupInRecycleBin = await this.isGroupInEntraRecycleBin(logger, siteDetails.GroupId);
|
|
83
|
+
amountOfPolls++;
|
|
81
84
|
}
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
if (isGroupInRecycleBin) {
|
|
86
|
+
await this.removeGroupFromEntraRecycleBin(logger, siteDetails.GroupId);
|
|
84
87
|
}
|
|
85
88
|
}
|
|
86
89
|
}
|
|
90
|
+
else {
|
|
91
|
+
await this.deleteNonGroupSite(logger, siteUrl);
|
|
92
|
+
}
|
|
93
|
+
if (options.skipRecycleBin) {
|
|
94
|
+
await this.deleteSiteFromSharePointRecycleBin(logger, siteUrl);
|
|
95
|
+
}
|
|
87
96
|
}
|
|
88
97
|
}
|
|
89
98
|
catch (err) {
|
|
90
|
-
this.
|
|
99
|
+
this.handleRejectedODataJsonPromise(err);
|
|
91
100
|
}
|
|
92
101
|
}
|
|
93
|
-
|
|
102
|
+
async removeGroupFromEntraRecycleBin(logger, groupId) {
|
|
103
|
+
if (this.verbose) {
|
|
104
|
+
await logger.logToStderr(`Permanently deleting group '${groupId}'.`);
|
|
105
|
+
}
|
|
94
106
|
const requestOptions = {
|
|
95
|
-
url: `https://graph.microsoft.com/v1.0/directory/deletedItems/Microsoft.Graph.Group
|
|
107
|
+
url: `https://graph.microsoft.com/v1.0/directory/deletedItems/Microsoft.Graph.Group/${groupId}`,
|
|
96
108
|
headers: {
|
|
97
109
|
accept: 'application/json;odata.metadata=none'
|
|
98
110
|
},
|
|
99
111
|
responseType: 'json'
|
|
100
112
|
};
|
|
101
|
-
return request.
|
|
113
|
+
return request.delete(requestOptions);
|
|
102
114
|
}
|
|
103
|
-
async
|
|
104
|
-
|
|
115
|
+
async isGroupInEntraRecycleBin(logger, groupId) {
|
|
116
|
+
if (this.verbose) {
|
|
117
|
+
await logger.logToStderr(`Checking if group '${groupId}' is in the Microsoft Entra recycle bin.`);
|
|
118
|
+
}
|
|
105
119
|
const requestOptions = {
|
|
106
|
-
url:
|
|
120
|
+
url: `https://graph.microsoft.com/v1.0/directory/deletedItems/Microsoft.Graph.Group/${groupId}?$select=id`,
|
|
107
121
|
headers: {
|
|
108
|
-
|
|
109
|
-
accept: 'application/json;odata=nometadata'
|
|
122
|
+
accept: 'application/json;odata.metadata=none'
|
|
110
123
|
},
|
|
111
124
|
responseType: 'json'
|
|
112
125
|
};
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
this.spoAdminUrl = await spo.getSpoAdminUrl(logger, this.debug);
|
|
117
|
-
this.context = await spo.ensureFormDigest(this.spoAdminUrl, logger, this.context, this.debug);
|
|
118
|
-
if (args.options.fromRecycleBin) {
|
|
119
|
-
if (this.verbose) {
|
|
120
|
-
await logger.logToStderr(`Deleting site from recycle bin ${args.options.url}...`);
|
|
121
|
-
}
|
|
122
|
-
await this.deleteSiteFromTheRecycleBin(args.options.url, args.options.wait, logger);
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
await this.deleteSite(args.options.url, args.options.wait, logger);
|
|
126
|
+
try {
|
|
127
|
+
await request.get(requestOptions);
|
|
128
|
+
return true;
|
|
126
129
|
}
|
|
127
|
-
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
+
catch (err) {
|
|
131
|
+
if (err.response?.status === 404) {
|
|
132
|
+
return false;
|
|
130
133
|
}
|
|
131
|
-
|
|
134
|
+
throw err;
|
|
132
135
|
}
|
|
133
136
|
}
|
|
134
|
-
async
|
|
135
|
-
this.context = await spo.ensureFormDigest(this.spoAdminUrl, logger, this.context, this.debug);
|
|
137
|
+
async deleteNonGroupSite(logger, siteUrl) {
|
|
136
138
|
if (this.verbose) {
|
|
137
|
-
await logger.logToStderr(`Deleting site
|
|
139
|
+
await logger.logToStderr(`Deleting site.`);
|
|
138
140
|
}
|
|
139
141
|
const requestOptions = {
|
|
140
|
-
url: `${this.spoAdminUrl}/
|
|
142
|
+
url: `${this.spoAdminUrl}/_api/Microsoft.Online.SharePoint.TenantAdministration.Tenant/RemoveSite`,
|
|
141
143
|
headers: {
|
|
142
|
-
'
|
|
144
|
+
accept: 'application/json;odata=nometadata'
|
|
143
145
|
},
|
|
144
|
-
data:
|
|
145
|
-
|
|
146
|
-
const response = await request.post(requestOptions);
|
|
147
|
-
const json = JSON.parse(response);
|
|
148
|
-
const responseContent = json[0];
|
|
149
|
-
if (responseContent.ErrorInfo) {
|
|
150
|
-
throw responseContent.ErrorInfo.ErrorMessage;
|
|
151
|
-
}
|
|
152
|
-
const operation = json[json.length - 1];
|
|
153
|
-
const isComplete = operation.IsComplete;
|
|
154
|
-
if (!wait || isComplete) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
await setTimeout(operation.PollingInterval);
|
|
158
|
-
await spo.waitUntilFinished({
|
|
159
|
-
operationId: JSON.stringify(operation._ObjectIdentity_),
|
|
160
|
-
siteUrl: this.spoAdminUrl,
|
|
161
|
-
logger,
|
|
162
|
-
currentContext: this.context,
|
|
163
|
-
debug: this.debug,
|
|
164
|
-
verbose: this.verbose
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
async deleteSiteFromTheRecycleBin(url, wait, logger) {
|
|
168
|
-
this.context = await spo.ensureFormDigest(this.spoAdminUrl, logger, this.context, this.debug);
|
|
169
|
-
const requestOptions = {
|
|
170
|
-
url: `${this.spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
|
|
171
|
-
headers: {
|
|
172
|
-
'X-RequestDigest': this.context.FormDigestValue
|
|
146
|
+
data: {
|
|
147
|
+
siteUrl: siteUrl
|
|
173
148
|
},
|
|
174
|
-
|
|
149
|
+
responseType: 'json'
|
|
175
150
|
};
|
|
176
|
-
|
|
177
|
-
const json = JSON.parse(response);
|
|
178
|
-
const responseContent = json[0];
|
|
179
|
-
if (responseContent.ErrorInfo) {
|
|
180
|
-
throw responseContent.ErrorInfo.ErrorMessage;
|
|
181
|
-
}
|
|
182
|
-
const operation = json[json.length - 1];
|
|
183
|
-
const isComplete = operation.IsComplete;
|
|
184
|
-
if (!wait || isComplete) {
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
await setTimeout(operation.PollingInterval);
|
|
188
|
-
await spo.waitUntilFinished({
|
|
189
|
-
operationId: JSON.stringify(operation._ObjectIdentity_),
|
|
190
|
-
siteUrl: this.spoAdminUrl,
|
|
191
|
-
logger,
|
|
192
|
-
currentContext: this.context,
|
|
193
|
-
debug: this.debug,
|
|
194
|
-
verbose: this.verbose
|
|
195
|
-
});
|
|
151
|
+
return request.post(requestOptions);
|
|
196
152
|
}
|
|
197
|
-
async
|
|
198
|
-
this.spoAdminUrl = await spo.getSpoAdminUrl(logger, this.debug);
|
|
199
|
-
this.context = await spo.ensureFormDigest(this.spoAdminUrl, logger, this.context, this.debug);
|
|
153
|
+
async deleteSiteFromSharePointRecycleBin(logger, url) {
|
|
200
154
|
if (this.verbose) {
|
|
201
|
-
await logger.logToStderr(`
|
|
155
|
+
await logger.logToStderr(`Permanently deleting site from the recycle bin.`);
|
|
202
156
|
}
|
|
203
157
|
const requestOptions = {
|
|
204
|
-
url: `${this.spoAdminUrl}/
|
|
158
|
+
url: `${this.spoAdminUrl}/_api/Microsoft.Online.SharePoint.TenantAdministration.Tenant/RemoveDeletedSite`,
|
|
205
159
|
headers: {
|
|
206
|
-
'
|
|
160
|
+
accept: 'application/json;odata=nometadata',
|
|
161
|
+
'Content-Type': 'application/json'
|
|
207
162
|
},
|
|
208
|
-
data:
|
|
163
|
+
data: {
|
|
164
|
+
siteUrl: url
|
|
165
|
+
},
|
|
166
|
+
responseType: 'json'
|
|
209
167
|
};
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (
|
|
214
|
-
|
|
168
|
+
return request.post(requestOptions);
|
|
169
|
+
}
|
|
170
|
+
async getSiteDetails(logger, url) {
|
|
171
|
+
if (this.verbose) {
|
|
172
|
+
await logger.logToStderr(`Retrieving site info.`);
|
|
215
173
|
}
|
|
216
|
-
const
|
|
217
|
-
|
|
174
|
+
const sites = await odata.getAllItems(`${this.spoAdminUrl}/_api/web/lists/GetByTitle('DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS')/items?$filter=SiteUrl eq '${formatting.encodeQueryParameter(url)}'&$select=GroupId,TimeDeleted,SiteId`);
|
|
175
|
+
if (sites.length === 0) {
|
|
176
|
+
throw `Site not found in the tenant.`;
|
|
177
|
+
}
|
|
178
|
+
return sites[0];
|
|
218
179
|
}
|
|
219
|
-
async
|
|
180
|
+
async deleteGroupifiedSite(logger, siteUrl) {
|
|
220
181
|
if (this.verbose) {
|
|
221
|
-
await logger.logToStderr(`Removing
|
|
182
|
+
await logger.logToStderr(`Removing groupified site.`);
|
|
222
183
|
}
|
|
223
184
|
const requestOptions = {
|
|
224
|
-
url:
|
|
185
|
+
url: `${this.spoAdminUrl}/_api/GroupSiteManager/Delete?siteUrl='${formatting.encodeQueryParameter(siteUrl)}'`,
|
|
225
186
|
headers: {
|
|
226
|
-
|
|
227
|
-
}
|
|
187
|
+
accept: 'application/json;odata=nometadata'
|
|
188
|
+
},
|
|
189
|
+
responseType: 'json'
|
|
228
190
|
};
|
|
229
|
-
return request.
|
|
191
|
+
return request.post(requestOptions);
|
|
230
192
|
}
|
|
231
193
|
}
|
|
232
194
|
_SpoSiteRemoveCommand_instances = new WeakSet(), _SpoSiteRemoveCommand_initTelemetry = function _SpoSiteRemoveCommand_initTelemetry() {
|
|
233
195
|
this.telemetry.push((args) => {
|
|
234
196
|
Object.assign(this.telemetryProperties, {
|
|
235
|
-
skipRecycleBin:
|
|
236
|
-
fromRecycleBin:
|
|
237
|
-
wait: args.options.wait,
|
|
238
|
-
force:
|
|
197
|
+
skipRecycleBin: !!args.options.skipRecycleBin,
|
|
198
|
+
fromRecycleBin: !!args.options.fromRecycleBin,
|
|
199
|
+
wait: !!args.options.wait,
|
|
200
|
+
force: !!args.options.force
|
|
239
201
|
});
|
|
240
202
|
});
|
|
241
203
|
}, _SpoSiteRemoveCommand_initOptions = function _SpoSiteRemoveCommand_initOptions() {
|
|
@@ -251,7 +213,24 @@ _SpoSiteRemoveCommand_instances = new WeakSet(), _SpoSiteRemoveCommand_initTelem
|
|
|
251
213
|
option: '-f, --force'
|
|
252
214
|
});
|
|
253
215
|
}, _SpoSiteRemoveCommand_initValidators = function _SpoSiteRemoveCommand_initValidators() {
|
|
254
|
-
this.validators.push(async (args) =>
|
|
216
|
+
this.validators.push(async (args) => {
|
|
217
|
+
const isValidSharePointUrl = validation.isValidSharePointUrl(args.options.url);
|
|
218
|
+
if (isValidSharePointUrl !== true) {
|
|
219
|
+
return isValidSharePointUrl;
|
|
220
|
+
}
|
|
221
|
+
const uri = new URL(args.options.url);
|
|
222
|
+
const rootUrl = `${uri.protocol}//${uri.hostname}`;
|
|
223
|
+
if (rootUrl.toLowerCase() === urlUtil.removeTrailingSlashes(args.options.url.toLowerCase())) {
|
|
224
|
+
return `The root site cannot be deleted.`;
|
|
225
|
+
}
|
|
226
|
+
if (args.options.fromRecycleBin && args.options.skipRecycleBin) {
|
|
227
|
+
return 'Specify either fromRecycleBin or skipRecycleBin, but not both.';
|
|
228
|
+
}
|
|
229
|
+
return true;
|
|
230
|
+
});
|
|
231
|
+
}, _SpoSiteRemoveCommand_initTypes = function _SpoSiteRemoveCommand_initTypes() {
|
|
232
|
+
this.types.string.push('url');
|
|
233
|
+
this.types.boolean.push('skipRecycleBin', 'fromRecycleBin', 'wait', 'force');
|
|
255
234
|
};
|
|
256
235
|
export default new SpoSiteRemoveCommand();
|
|
257
236
|
//# sourceMappingURL=site-remove.js.map
|
|
@@ -3,8 +3,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
3
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
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
|
-
var _SpoSetCommand_instances, _SpoSetCommand_initOptions, _SpoSetCommand_initValidators;
|
|
6
|
+
var _SpoSetCommand_instances, _SpoSetCommand_initOptions, _SpoSetCommand_initValidators, _SpoSetCommand_initTypes;
|
|
7
7
|
import auth from '../../../Auth.js';
|
|
8
|
+
import { urlUtil } from '../../../utils/urlUtil.js';
|
|
8
9
|
import { validation } from '../../../utils/validation.js';
|
|
9
10
|
import SpoCommand from '../../base/SpoCommand.js';
|
|
10
11
|
import commands from '../commands.js';
|
|
@@ -20,9 +21,10 @@ class SpoSetCommand extends SpoCommand {
|
|
|
20
21
|
_SpoSetCommand_instances.add(this);
|
|
21
22
|
__classPrivateFieldGet(this, _SpoSetCommand_instances, "m", _SpoSetCommand_initOptions).call(this);
|
|
22
23
|
__classPrivateFieldGet(this, _SpoSetCommand_instances, "m", _SpoSetCommand_initValidators).call(this);
|
|
24
|
+
__classPrivateFieldGet(this, _SpoSetCommand_instances, "m", _SpoSetCommand_initTypes).call(this);
|
|
23
25
|
}
|
|
24
26
|
async commandAction(logger, args) {
|
|
25
|
-
auth.connection.spoUrl = args.options.url;
|
|
27
|
+
auth.connection.spoUrl = urlUtil.removeTrailingSlashes(args.options.url);
|
|
26
28
|
try {
|
|
27
29
|
await auth.storeConnectionInfo();
|
|
28
30
|
}
|
|
@@ -37,6 +39,8 @@ _SpoSetCommand_instances = new WeakSet(), _SpoSetCommand_initOptions = function
|
|
|
37
39
|
});
|
|
38
40
|
}, _SpoSetCommand_initValidators = function _SpoSetCommand_initValidators() {
|
|
39
41
|
this.validators.push(async (args) => validation.isValidSharePointUrl(args.options.url));
|
|
42
|
+
}, _SpoSetCommand_initTypes = function _SpoSetCommand_initTypes() {
|
|
43
|
+
this.types.string.push('url');
|
|
40
44
|
};
|
|
41
45
|
export default new SpoSetCommand();
|
|
42
46
|
//# sourceMappingURL=spo-set.js.map
|
|
@@ -164,6 +164,7 @@ export default {
|
|
|
164
164
|
LISTITEM_ATTACHMENT_REMOVE: `${prefix} listitem attachment remove`,
|
|
165
165
|
LISTITEM_ATTACHMENT_SET: `${prefix} listitem attachment set`,
|
|
166
166
|
LISTITEM_BATCH_ADD: `${prefix} listitem batch add`,
|
|
167
|
+
LISTITEM_BATCH_REMOVE: `${prefix} listitem batch remove`,
|
|
167
168
|
LISTITEM_BATCH_SET: `${prefix} listitem batch set`,
|
|
168
169
|
LISTITEM_GET: `${prefix} listitem get`,
|
|
169
170
|
LISTITEM_ISRECORD: `${prefix} listitem isrecord`,
|
|
@@ -136,9 +136,9 @@ _TeamsMeetingAddCommand_instances = new WeakSet(), _TeamsMeetingAddCommand_initT
|
|
|
136
136
|
return 'The endTime value must be in the future.';
|
|
137
137
|
}
|
|
138
138
|
if (args.options.participantUserNames) {
|
|
139
|
-
const
|
|
140
|
-
if (
|
|
141
|
-
return `
|
|
139
|
+
const isValidUPNArrayResult = validation.isValidUserPrincipalNameArray(args.options.participantUserNames);
|
|
140
|
+
if (isValidUPNArrayResult !== true) {
|
|
141
|
+
return `The following user principal names are invalid for the option 'participantUserNames': ${isValidUPNArrayResult}.`;
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
if (args.options.organizerEmail && !validation.isValidUserPrincipalName(args.options.organizerEmail)) {
|
|
@@ -226,34 +226,40 @@ _TeamsTeamAddCommand_instances = new WeakSet(), _TeamsTeamAddCommand_initTelemet
|
|
|
226
226
|
}, _TeamsTeamAddCommand_initValidators = function _TeamsTeamAddCommand_initValidators() {
|
|
227
227
|
this.validators.push(async (args) => {
|
|
228
228
|
if (args.options.ownerUserNames) {
|
|
229
|
-
const
|
|
230
|
-
if (
|
|
231
|
-
return `
|
|
229
|
+
const isValidUPNArrayResult = validation.isValidUserPrincipalNameArray(args.options.ownerUserNames);
|
|
230
|
+
if (isValidUPNArrayResult !== true) {
|
|
231
|
+
return `The following user principal names are invalid for the option 'ownerUserNames': ${isValidUPNArrayResult}.`;
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
if (args.options.ownerEmails) {
|
|
235
|
-
const
|
|
236
|
-
if (
|
|
237
|
-
return `
|
|
235
|
+
const isValidUPNArrayResult = validation.isValidUserPrincipalNameArray(args.options.ownerEmails);
|
|
236
|
+
if (isValidUPNArrayResult !== true) {
|
|
237
|
+
return `The following user principal names are invalid for the option 'ownerEmails': ${isValidUPNArrayResult}.`;
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
|
-
if (args.options.ownerIds
|
|
241
|
-
|
|
240
|
+
if (args.options.ownerIds) {
|
|
241
|
+
const isValidGUIDArrayResult = validation.isValidGuidArray(args.options.ownerIds);
|
|
242
|
+
if (isValidGUIDArrayResult !== true) {
|
|
243
|
+
return `The following GUIDs are invalid for the option 'ownerIds': ${isValidGUIDArrayResult}.`;
|
|
244
|
+
}
|
|
242
245
|
}
|
|
243
246
|
if (args.options.memberUserNames) {
|
|
244
|
-
const
|
|
245
|
-
if (
|
|
246
|
-
return `
|
|
247
|
+
const isValidUPNArrayResult = validation.isValidUserPrincipalNameArray(args.options.memberUserNames);
|
|
248
|
+
if (isValidUPNArrayResult !== true) {
|
|
249
|
+
return `The following user principal names are invalid for the option 'memberUserNames': ${isValidUPNArrayResult}.`;
|
|
247
250
|
}
|
|
248
251
|
}
|
|
249
252
|
if (args.options.memberEmails) {
|
|
250
|
-
const
|
|
251
|
-
if (
|
|
252
|
-
return `
|
|
253
|
+
const isValidUPNArrayResult = validation.isValidUserPrincipalNameArray(args.options.memberEmails);
|
|
254
|
+
if (isValidUPNArrayResult !== true) {
|
|
255
|
+
return `The following user principal names are invalid for the option 'memberEmails': ${isValidUPNArrayResult}.`;
|
|
253
256
|
}
|
|
254
257
|
}
|
|
255
|
-
if (args.options.memberIds
|
|
256
|
-
|
|
258
|
+
if (args.options.memberIds) {
|
|
259
|
+
const isValidGUIDArrayResult = validation.isValidGuidArray(args.options.memberIds);
|
|
260
|
+
if (isValidGUIDArrayResult !== true) {
|
|
261
|
+
return `The following GUIDs are invalid for the option 'memberIds': ${isValidGUIDArrayResult}.`;
|
|
262
|
+
}
|
|
257
263
|
}
|
|
258
264
|
return true;
|
|
259
265
|
});
|
package/dist/utils/planner.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { cli } from "../cli/cli.js";
|
|
1
2
|
import request from "../request.js";
|
|
3
|
+
import { formatting } from "./formatting.js";
|
|
2
4
|
import { odata } from "./odata.js";
|
|
3
5
|
const graphResource = 'https://graph.microsoft.com';
|
|
4
6
|
const getRequestOptions = (url, metadata) => ({
|
|
@@ -12,7 +14,8 @@ export const planner = {
|
|
|
12
14
|
/**
|
|
13
15
|
* Get Planner plan by ID.
|
|
14
16
|
* @param id Planner ID.
|
|
15
|
-
* @param metadata OData metadata level. Default is none
|
|
17
|
+
* @param metadata OData metadata level. Default is none.
|
|
18
|
+
* @throws Error when the plan is not found.
|
|
16
19
|
*/
|
|
17
20
|
async getPlanById(id, metadata = 'none') {
|
|
18
21
|
const requestOptions = getRequestOptions(`${graphResource}/v1.0/planner/plans/${id}`, metadata);
|
|
@@ -26,6 +29,7 @@ export const planner = {
|
|
|
26
29
|
/**
|
|
27
30
|
* Get all Planner plans for a specific group.
|
|
28
31
|
* @param groupId Group ID.
|
|
32
|
+
* @param metadata OData metadata level. Default is none.
|
|
29
33
|
*/
|
|
30
34
|
getPlansByGroupId(groupId, metadata = 'none') {
|
|
31
35
|
return odata.getAllItems(`${graphResource}/v1.0/groups/${groupId}/planner/plans`, metadata);
|
|
@@ -33,30 +37,105 @@ export const planner = {
|
|
|
33
37
|
/**
|
|
34
38
|
* Get the Planner plan for a specific Roster.
|
|
35
39
|
* @param rosterId Roster ID.
|
|
40
|
+
* @param metadata OData metadata level. Default is none.
|
|
41
|
+
* @throws Error when the roster has no plan.
|
|
36
42
|
*/
|
|
37
43
|
async getPlanByRosterId(rosterId, metadata = 'none') {
|
|
38
44
|
const plans = await odata.getAllItems(`${graphResource}/beta/planner/rosters/${rosterId}/plans`, metadata);
|
|
45
|
+
if (plans.length === 0) {
|
|
46
|
+
throw Error(`The specified roster '${rosterId}' does not have a plan.`);
|
|
47
|
+
}
|
|
39
48
|
return plans[0];
|
|
40
49
|
},
|
|
50
|
+
/**
|
|
51
|
+
* Get the Planner plan ID for a specific Roster.
|
|
52
|
+
* @param rosterId Roster ID.
|
|
53
|
+
* @throws Error when the roster has no plan.
|
|
54
|
+
*/
|
|
55
|
+
async getPlanIdByRosterId(rosterId) {
|
|
56
|
+
const plans = await odata.getAllItems(`${graphResource}/beta/planner/rosters/${rosterId}/plans?$select=id`);
|
|
57
|
+
if (plans.length === 0) {
|
|
58
|
+
throw Error(`The specified roster '${rosterId}' does not have a plan.`);
|
|
59
|
+
}
|
|
60
|
+
return plans[0].id;
|
|
61
|
+
},
|
|
41
62
|
/**
|
|
42
63
|
* Get Planner plan by title in a specific group.
|
|
43
64
|
* @param title Title of the Planner plan. Case insensitive.
|
|
44
65
|
* @param groupId Owner group ID.
|
|
45
|
-
* @param
|
|
66
|
+
* @param metadata OData metadata level. Default is none.
|
|
67
|
+
* @throws Error when the plan is not found.
|
|
46
68
|
*/
|
|
47
69
|
async getPlanByTitle(title, groupId, metadata = 'none') {
|
|
48
|
-
|
|
49
|
-
if (groupId) {
|
|
50
|
-
plans = await this.getPlansByGroupId(groupId, metadata);
|
|
51
|
-
}
|
|
70
|
+
const plans = await this.getPlansByGroupId(groupId, metadata);
|
|
52
71
|
const filteredPlans = plans.filter(p => p.title && p.title.toLowerCase() === title.toLowerCase());
|
|
53
|
-
if (
|
|
72
|
+
if (filteredPlans.length === 0) {
|
|
54
73
|
throw Error(`The specified plan '${title}' does not exist.`);
|
|
55
74
|
}
|
|
56
75
|
if (filteredPlans.length > 1) {
|
|
57
|
-
|
|
76
|
+
const plansKeyValuePair = formatting.convertArrayToHashTable('id', filteredPlans);
|
|
77
|
+
const plan = await cli.handleMultipleResultsFound(`Multiple plans with title '${title}' found.`, plansKeyValuePair);
|
|
78
|
+
return plan;
|
|
58
79
|
}
|
|
59
80
|
return filteredPlans[0];
|
|
81
|
+
},
|
|
82
|
+
/**
|
|
83
|
+
* Get Planner plan ID by title in a specific group.
|
|
84
|
+
* @param title Title of the Planner plan. Case insensitive.
|
|
85
|
+
* @param groupId Owner group ID.
|
|
86
|
+
* @throws Error when the plan is not found.
|
|
87
|
+
*/
|
|
88
|
+
async getPlanIdByTitle(title, groupId) {
|
|
89
|
+
const plans = await odata.getAllItems(`${graphResource}/v1.0/groups/${groupId}/planner/plans?$select=id,title`);
|
|
90
|
+
const filteredPlans = plans.filter(p => p.title && p.title.toLowerCase() === title.toLowerCase());
|
|
91
|
+
if (filteredPlans.length === 0) {
|
|
92
|
+
throw Error(`The specified plan '${title}' does not exist.`);
|
|
93
|
+
}
|
|
94
|
+
if (filteredPlans.length > 1) {
|
|
95
|
+
const plansKeyValuePair = formatting.convertArrayToHashTable('id', filteredPlans);
|
|
96
|
+
const plan = await cli.handleMultipleResultsFound(`Multiple plans with title '${title}' found.`, plansKeyValuePair);
|
|
97
|
+
return plan.id;
|
|
98
|
+
}
|
|
99
|
+
return filteredPlans[0].id;
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
* Get Planner bucket by title in a specific plan.
|
|
103
|
+
* @param title Title of the Planner bucket. Case insensitive.
|
|
104
|
+
* @param planId ID of the plan that contains the bucket.
|
|
105
|
+
* @param metadata OData metadata level. Default is none.
|
|
106
|
+
* @throws Error when the bucket is not found.
|
|
107
|
+
*/
|
|
108
|
+
async getBucketByTitle(title, planId, metadata = 'none') {
|
|
109
|
+
const buckets = await odata.getAllItems(`${graphResource}/v1.0/planner/plans/${planId}/buckets`, metadata);
|
|
110
|
+
const filteredBuckets = buckets.filter(b => b.name && b.name.toLowerCase() === title.toLowerCase());
|
|
111
|
+
if (filteredBuckets.length === 0) {
|
|
112
|
+
throw Error(`The specified bucket '${title}' does not exist.`);
|
|
113
|
+
}
|
|
114
|
+
if (filteredBuckets.length > 1) {
|
|
115
|
+
const bucketsKeyValuePair = formatting.convertArrayToHashTable('id', filteredBuckets);
|
|
116
|
+
const bucket = await cli.handleMultipleResultsFound(`Multiple buckets with name '${title}' found.`, bucketsKeyValuePair);
|
|
117
|
+
return bucket;
|
|
118
|
+
}
|
|
119
|
+
return filteredBuckets[0];
|
|
120
|
+
},
|
|
121
|
+
/**
|
|
122
|
+
* Get Planner bucket ID by title in a specific plan.
|
|
123
|
+
* @param title Title of the Planner bucket. Case insensitive.
|
|
124
|
+
* @param planId ID of the plan that contains the bucket.
|
|
125
|
+
* @throws Error when the bucket is not found.
|
|
126
|
+
*/
|
|
127
|
+
async getBucketIdByTitle(title, planId) {
|
|
128
|
+
const buckets = await odata.getAllItems(`${graphResource}/v1.0/planner/plans/${planId}/buckets?$select=id,name`);
|
|
129
|
+
const filteredBuckets = buckets.filter(b => b.name && b.name.toLowerCase() === title.toLowerCase());
|
|
130
|
+
if (filteredBuckets.length === 0) {
|
|
131
|
+
throw Error(`The specified bucket '${title}' does not exist.`);
|
|
132
|
+
}
|
|
133
|
+
if (filteredBuckets.length > 1) {
|
|
134
|
+
const bucketsKeyValuePair = formatting.convertArrayToHashTable('id', filteredBuckets);
|
|
135
|
+
const bucket = await cli.handleMultipleResultsFound(`Multiple buckets with name '${title}' found.`, bucketsKeyValuePair);
|
|
136
|
+
return bucket.id;
|
|
137
|
+
}
|
|
138
|
+
return filteredBuckets[0].id;
|
|
60
139
|
}
|
|
61
140
|
};
|
|
62
141
|
//# sourceMappingURL=planner.js.map
|