@pnp/cli-microsoft365 11.6.0-beta.358a4f1 → 11.6.0-beta.bc374af

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 (31) hide show
  1. package/.devproxy/api-specs/sharepoint-admin.yaml +40 -0
  2. package/.devproxy/api-specs/sharepoint.yaml +48 -0
  3. package/allCommands.json +1 -1
  4. package/allCommandsFull.json +1 -1
  5. package/dist/m365/entra/commands/user/user-recyclebinitem-list.js +5 -0
  6. package/dist/m365/outlook/commands/calendargroup/calendargroup-list.js +87 -0
  7. package/dist/m365/outlook/commands.js +1 -0
  8. package/dist/m365/spo/commands/agent/agent-add.js +172 -0
  9. package/dist/m365/spo/commands/list/list-set.js +186 -378
  10. package/dist/m365/spo/commands/navigation/navigation-node-get.js +18 -28
  11. package/dist/m365/spo/commands/navigation/navigation-node-list.js +14 -39
  12. package/dist/m365/spo/commands/site/site-accessrequest-setting-set.js +102 -0
  13. package/dist/m365/spo/commands/site/site-add.js +38 -8
  14. package/dist/m365/spo/commands/tenant/tenant-site-get.js +112 -0
  15. package/dist/m365/spo/commands.js +3 -0
  16. package/dist/utils/accessToken.js +21 -0
  17. package/dist/utils/brandCenter.js +29 -0
  18. package/docs/docs/cmd/entra/app/app-role-add.mdx +21 -0
  19. package/docs/docs/cmd/entra/app/app-role-list.mdx +20 -1
  20. package/docs/docs/cmd/entra/app/app-role-remove.mdx +22 -1
  21. package/docs/docs/cmd/entra/policy/policy-list.mdx +19 -0
  22. package/docs/docs/cmd/entra/resourcenamespace/resourcenamespace-list.mdx +19 -0
  23. package/docs/docs/cmd/outlook/calendargroup/calendargroup-list.mdx +120 -0
  24. package/docs/docs/cmd/spo/agent/agent-add.mdx +190 -0
  25. package/docs/docs/cmd/spo/list/list-set.mdx +19 -1
  26. package/docs/docs/cmd/spo/navigation/navigation-node-get.mdx +43 -10
  27. package/docs/docs/cmd/spo/navigation/navigation-node-list.mdx +36 -3
  28. package/docs/docs/cmd/spo/site/site-accessrequest-setting-set.mdx +77 -0
  29. package/docs/docs/cmd/spo/site/site-add.mdx +14 -5
  30. package/docs/docs/cmd/spo/tenant/tenant-site-get.mdx +479 -0
  31. package/package.json +1 -1
@@ -1,6 +1,8 @@
1
+ import { globalOptionsZod } from '../../../../Command.js';
1
2
  import { odata } from '../../../../utils/odata.js';
2
3
  import GraphCommand from '../../../base/GraphCommand.js';
3
4
  import commands from '../../commands.js';
5
+ export const options = globalOptionsZod.strict();
4
6
  class EntraUserRecycleBinItemListCommand extends GraphCommand {
5
7
  get name() {
6
8
  return commands.USER_RECYCLEBINITEM_LIST;
@@ -8,6 +10,9 @@ class EntraUserRecycleBinItemListCommand extends GraphCommand {
8
10
  get description() {
9
11
  return 'Lists users from the recycle bin in the current tenant';
10
12
  }
13
+ get schema() {
14
+ return options;
15
+ }
11
16
  defaultProperties() {
12
17
  return ['id', 'displayName', 'userPrincipalName'];
13
18
  }
@@ -0,0 +1,87 @@
1
+ import { z } from 'zod';
2
+ import { globalOptionsZod } from '../../../../Command.js';
3
+ import GraphCommand from '../../../base/GraphCommand.js';
4
+ import commands from '../../commands.js';
5
+ import { validation } from '../../../../utils/validation.js';
6
+ import { odata } from '../../../../utils/odata.js';
7
+ import { accessToken } from '../../../../utils/accessToken.js';
8
+ import auth from '../../../../Auth.js';
9
+ export const options = z.strictObject({
10
+ ...globalOptionsZod.shape,
11
+ userId: z.string().refine(id => validation.isValidGuid(id), {
12
+ error: e => `'${e.input}' is not a valid GUID.`
13
+ }).optional(),
14
+ userName: z.string().refine(name => validation.isValidUserPrincipalName(name), {
15
+ error: e => `'${e.input}' is not a valid UPN.`
16
+ }).optional()
17
+ });
18
+ class OutlookCalendarGroupListCommand extends GraphCommand {
19
+ get name() {
20
+ return commands.CALENDARGROUP_LIST;
21
+ }
22
+ get description() {
23
+ return 'Retrieves calendar groups for a user';
24
+ }
25
+ get schema() {
26
+ return options;
27
+ }
28
+ getRefinedSchema(schema) {
29
+ return schema
30
+ .refine(options => !(options.userId && options.userName), {
31
+ error: 'Specify either userId or userName, but not both.'
32
+ });
33
+ }
34
+ defaultProperties() {
35
+ return ['id', 'name'];
36
+ }
37
+ async commandAction(logger, args) {
38
+ try {
39
+ const token = auth.connection.accessTokens[auth.defaultResource].accessToken;
40
+ const isAppOnlyAccessToken = accessToken.isAppOnlyAccessToken(token);
41
+ if (isAppOnlyAccessToken) {
42
+ if (!args.options.userId && !args.options.userName) {
43
+ throw 'When running with application permissions either userId or userName is required.';
44
+ }
45
+ const userIdentifier = args.options.userId ?? args.options.userName;
46
+ if (this.verbose) {
47
+ await logger.logToStderr(`Retrieving calendar groups for user '${userIdentifier}'...`);
48
+ }
49
+ const calendarGroups = await odata.getAllItems(`${this.resource}/v1.0/users('${userIdentifier}')/calendarGroups`);
50
+ await logger.log(calendarGroups);
51
+ }
52
+ else {
53
+ if (args.options.userId || args.options.userName) {
54
+ const currentUserId = accessToken.getUserIdFromAccessToken(token);
55
+ const currentUserName = accessToken.getUserNameFromAccessToken(token);
56
+ const isOtherUser = (args.options.userId && args.options.userId !== currentUserId) ||
57
+ (args.options.userName && args.options.userName.toLowerCase() !== currentUserName?.toLowerCase());
58
+ if (isOtherUser) {
59
+ const scopes = accessToken.getScopesFromAccessToken(token);
60
+ const hasSharedScope = scopes.some(s => s === 'Calendars.Read.Shared' || s === 'Calendars.ReadWrite.Shared');
61
+ if (!hasSharedScope) {
62
+ throw `To retrieve calendar groups of other users, the Entra ID application used for authentication must have either the Calendars.Read.Shared or Calendars.ReadWrite.Shared delegated permission assigned.`;
63
+ }
64
+ }
65
+ const userIdentifier = args.options.userId ?? args.options.userName;
66
+ if (this.verbose) {
67
+ await logger.logToStderr(`Retrieving calendar groups for user '${userIdentifier}'...`);
68
+ }
69
+ const calendarGroups = await odata.getAllItems(`${this.resource}/v1.0/users('${userIdentifier}')/calendarGroups`);
70
+ await logger.log(calendarGroups);
71
+ }
72
+ else {
73
+ if (this.verbose) {
74
+ await logger.logToStderr('Retrieving calendar groups for the signed-in user...');
75
+ }
76
+ const calendarGroups = await odata.getAllItems(`${this.resource}/v1.0/me/calendarGroups`);
77
+ await logger.log(calendarGroups);
78
+ }
79
+ }
80
+ }
81
+ catch (err) {
82
+ this.handleRejectedODataJsonPromise(err);
83
+ }
84
+ }
85
+ }
86
+ export default new OutlookCalendarGroupListCommand();
87
+ //# sourceMappingURL=calendargroup-list.js.map
@@ -1,5 +1,6 @@
1
1
  const prefix = 'outlook';
2
2
  export default {
3
+ CALENDARGROUP_LIST: `${prefix} calendargroup list`,
3
4
  MAIL_SEARCHFOLDER_ADD: `${prefix} mail searchfolder add`,
4
5
  MAIL_SEND: `${prefix} mail send`,
5
6
  MAILBOX_SETTINGS_GET: `${prefix} mailbox settings get`,
@@ -0,0 +1,172 @@
1
+ /* eslint-disable camelcase */
2
+ import { z } from 'zod';
3
+ import { globalOptionsZod } from '../../../../Command.js';
4
+ import request from '../../../../request.js';
5
+ import { validation } from '../../../../utils/validation.js';
6
+ import SpoCommand from '../../../base/SpoCommand.js';
7
+ import commands from '../../commands.js';
8
+ import { urlUtil } from '../../../../utils/urlUtil.js';
9
+ import { spo } from '../../../../utils/spo.js';
10
+ import { formatting } from '../../../../utils/formatting.js';
11
+ const options = z.strictObject({
12
+ ...globalOptionsZod.shape,
13
+ webUrl: z.string().alias('u').refine(url => validation.isValidSharePointUrl(url) === true, {
14
+ message: 'Specify a valid SharePoint site URL'
15
+ }),
16
+ name: z.string().alias('n'),
17
+ agentInstructions: z.string().alias('a'),
18
+ welcomeMessage: z.string().alias('w'),
19
+ sourceUrls: z.string().alias('s').refine(urls => {
20
+ const urlArray = urls.split(',').map(url => url.trim());
21
+ return urlArray.every(url => url && validation.isValidSharePointUrl(url) === true);
22
+ }, {
23
+ message: 'All source URLs must be valid SharePoint URLs'
24
+ }),
25
+ description: z.string().alias('d'),
26
+ icon: z.string().optional().alias('i'),
27
+ conversationStarters: z.string().optional().alias('c')
28
+ });
29
+ const urlSourceMap = {
30
+ STS_ListItem_DocumentLibrary: 'File',
31
+ STS_List_DocumentLibrary: 'List',
32
+ STS_Web: 'Site',
33
+ STS_Site: 'Site'
34
+ };
35
+ class SpoAgentAddCommand extends SpoCommand {
36
+ get name() {
37
+ return commands.AGENT_ADD;
38
+ }
39
+ get description() {
40
+ return 'Adds a new SharePoint agent';
41
+ }
42
+ get schema() {
43
+ return options;
44
+ }
45
+ async commandAction(logger, args) {
46
+ try {
47
+ if (this.verbose) {
48
+ await logger.logToStderr(`Adding SharePoint agent '${args.options.name}' to site '${args.options.webUrl}'...`);
49
+ }
50
+ await this.ensureSiteAssetsLibrary(args.options.webUrl, logger);
51
+ await spo.ensureFolder(args.options.webUrl, 'SiteAssets/Copilots', logger, this.verbose);
52
+ const sourceUrls = args.options.sourceUrls.split(',');
53
+ const capabilities = await this.resolveSourceUrls(sourceUrls, args.options.webUrl, logger);
54
+ const conversationStartersArray = args.options.conversationStarters
55
+ ? args.options.conversationStarters.split(',').map((starter) => { return { text: starter }; })
56
+ : [];
57
+ const cliM365DefaultIcon = 'data:image/png;base64,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';
58
+ const requestBody = {
59
+ schemaVersion: "0.2.0",
60
+ customCopilotConfig: {
61
+ conversationStarters: {
62
+ conversationStarterList: conversationStartersArray,
63
+ welcomeMessage: {
64
+ text: args.options.welcomeMessage
65
+ }
66
+ },
67
+ gptDefinition: {
68
+ name: args.options.name,
69
+ description: args.options.description,
70
+ instructions: args.options.agentInstructions,
71
+ capabilities: [capabilities]
72
+ },
73
+ icon: args.options.icon || cliM365DefaultIcon
74
+ }
75
+ };
76
+ const serverRelativePath = urlUtil.getServerRelativePath(args.options.webUrl, '/SiteAssets/Copilots/');
77
+ const requestOptions = {
78
+ url: `${args.options.webUrl}/_api/web/GetFolderByServerRelativePath(DecodedUrl='${serverRelativePath}')/Files/AddUsingPath(DecodedUrl='${formatting.encodeQueryParameter(args.options.name)}.agent',EnsureUniqueFileName=true,AutoCheckoutOnInvalidData=true)`,
79
+ headers: {
80
+ 'Accept': 'application/json;odata=nometadata',
81
+ 'Content-Type': 'application/json;odata=nometadata'
82
+ },
83
+ data: requestBody,
84
+ responseType: 'json'
85
+ };
86
+ const result = await request.post(requestOptions);
87
+ if (this.verbose) {
88
+ await logger.logToStderr(`Agent '${args.options.name}' has been successfully created.`);
89
+ }
90
+ await logger.log(result);
91
+ }
92
+ catch (err) {
93
+ this.handleRejectedODataJsonPromise(err);
94
+ }
95
+ }
96
+ async ensureSiteAssetsLibrary(webUrl, logger) {
97
+ if (this.verbose) {
98
+ await logger.logToStderr(`Ensuring Site Assets library exists at ${webUrl}...`);
99
+ }
100
+ const requestOptions = {
101
+ url: `${webUrl}/_api/web/lists/EnsureSiteAssetsLibrary()`,
102
+ headers: {
103
+ 'Accept': 'application/json;odata=nometadata'
104
+ },
105
+ responseType: 'json'
106
+ };
107
+ await request.post(requestOptions);
108
+ }
109
+ async resolveSourceUrls(sourceUrls, webUrl, logger) {
110
+ const resolvedUrls = [];
111
+ const resolvedFiles = [];
112
+ for (const sourceUrl of sourceUrls) {
113
+ if (this.verbose) {
114
+ await logger.logToStderr(`Resolving source URL: ${sourceUrl}`);
115
+ }
116
+ const requestBody = {
117
+ request: {
118
+ QueryTemplate: "({searchterms}) (contentclass:STS_Web OR contentclass:STS_Site OR contentclass:STS_ListItem_DocumentLibrary OR contentclass:STS_List_DocumentLibrary)",
119
+ Querytext: `Path="${sourceUrl}"`,
120
+ SelectProperties: ["contentclass", "Title", "Path", "SiteName", "SiteTitle", "ListID", "ListItemID", "SiteID", "WebId", "UniqueID", "IsDocument", "IsContainer"],
121
+ RowLimit: 1,
122
+ TrimDuplicates: false
123
+ }
124
+ };
125
+ const requestOptions = {
126
+ url: `${webUrl}/_api/search/postquery`,
127
+ headers: {
128
+ 'Accept': 'application/json;odata=nometadata'
129
+ },
130
+ responseType: 'json',
131
+ data: requestBody
132
+ };
133
+ const response = await request.post(requestOptions);
134
+ if (response.PrimaryQueryResult.RelevantResults.Table.Rows.length === 0) {
135
+ await logger.logToStderr(`${sourceUrl} has been skipped because no results were found.`);
136
+ continue;
137
+ }
138
+ const row = response.PrimaryQueryResult.RelevantResults.Table.Rows[0];
139
+ const isContainer = this.getCellValue(row, "IsContainer");
140
+ let uniqueId = this.getCellValue(row, "UniqueID");
141
+ if (uniqueId.startsWith('{') && uniqueId.endsWith('}')) {
142
+ uniqueId = uniqueId.slice(1, -1);
143
+ }
144
+ const contentClass = this.getCellValue(row, "contentclass");
145
+ const resolvedItem = {
146
+ url: sourceUrl,
147
+ name: this.getCellValue(row, "Title"),
148
+ site_id: this.getCellValue(row, "SiteID"),
149
+ web_id: this.getCellValue(row, "WebId"),
150
+ list_id: this.getCellValue(row, "ListID") || '',
151
+ unique_id: uniqueId,
152
+ type: isContainer === 'true' && contentClass === 'STS_ListItem_DocumentLibrary' ? 'Folder' : urlSourceMap[contentClass]
153
+ };
154
+ if (resolvedItem.type === 'File') {
155
+ resolvedFiles.push(resolvedItem);
156
+ }
157
+ else {
158
+ resolvedUrls.push(resolvedItem);
159
+ }
160
+ }
161
+ return {
162
+ name: "OneDriveAndSharePoint",
163
+ items_by_sharepoint_ids: resolvedFiles,
164
+ items_by_url: resolvedUrls
165
+ };
166
+ }
167
+ getCellValue(row, key) {
168
+ return row.Cells.find((cell) => cell.Key === key)?.Value || '';
169
+ }
170
+ }
171
+ export default new SpoAgentAddCommand();
172
+ //# sourceMappingURL=agent-add.js.map