@pnp/cli-microsoft365 10.9.0 → 10.10.0-beta.1bb5ba0

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 (84) hide show
  1. package/.devproxy/api-specs/sharepoint-admin.yaml +67 -0
  2. package/.devproxy/api-specs/sharepoint.yaml +230 -0
  3. package/.devproxy/devproxyrc.json +48 -0
  4. package/.devproxy/generate-openapi-spec.json +24 -0
  5. package/.devproxy/spo-csom-types.json +54 -0
  6. package/.eslintrc.cjs +8 -0
  7. package/allCommands.json +1 -1
  8. package/allCommandsFull.json +1 -1
  9. package/dist/cli/cli.js +2 -2
  10. package/dist/m365/app/commands/permission/permission-add.js +8 -1
  11. package/dist/m365/base/SpoCommand.js +1 -0
  12. package/dist/m365/entra/commands/app/app-permission-add.js +5 -18
  13. package/dist/m365/entra/commands/organization/organization-set.js +104 -0
  14. package/dist/m365/entra/commands.js +1 -0
  15. package/dist/m365/file/commands/file-copy.js +2 -2
  16. package/dist/m365/file/commands/file-move.js +1 -1
  17. package/dist/m365/planner/commands/tenant/tenant-settings-list.js +0 -3
  18. package/dist/m365/spo/commands/contenttype/contenttype-add.js +3 -65
  19. package/dist/m365/spo/commands/contenttype/contenttype-field-remove.js +5 -50
  20. package/dist/m365/spo/commands/contenttype/contenttype-field-set.js +4 -48
  21. package/dist/m365/spo/commands/contenttype/contenttype-set.js +8 -58
  22. package/dist/m365/spo/commands/contenttype/contenttype-sync.js +2 -2
  23. package/dist/m365/spo/commands/folder/folder-sharinglink-add.js +1 -1
  24. package/dist/m365/spo/commands/folder/folder-sharinglink-clear.js +1 -1
  25. package/dist/m365/spo/commands/folder/folder-sharinglink-get.js +1 -1
  26. package/dist/m365/spo/commands/folder/folder-sharinglink-list.js +1 -1
  27. package/dist/m365/spo/commands/folder/folder-sharinglink-remove.js +1 -1
  28. package/dist/m365/spo/commands/folder/folder-sharinglink-set.js +1 -1
  29. package/dist/m365/spo/commands/list/list-view-add.js +140 -87
  30. package/dist/m365/spo/commands/listitem/listitem-batch-set.js +3 -27
  31. package/dist/m365/spo/commands/page/Page.js +16 -1
  32. package/dist/m365/spo/commands/page/clientsidepages.js +4 -0
  33. package/dist/m365/spo/commands/page/page-add.js +1 -1
  34. package/dist/m365/spo/commands/page/page-clientsidewebpart-add.js +2 -8
  35. package/dist/m365/spo/commands/page/page-control-remove.js +99 -0
  36. package/dist/m365/spo/commands/page/page-control-set.js +1 -1
  37. package/dist/m365/spo/commands/page/page-header-set.js +9 -40
  38. package/dist/m365/spo/commands/page/page-publish.js +2 -10
  39. package/dist/m365/spo/commands/page/page-section-add.js +75 -21
  40. package/dist/m365/spo/commands/page/page-set.js +1 -1
  41. package/dist/m365/spo/commands/site/site-admin-add.js +1 -12
  42. package/dist/m365/spo/commands/site/site-set.js +2 -2
  43. package/dist/m365/spo/commands.js +1 -0
  44. package/dist/utils/entraServicePrincipal.js +21 -0
  45. package/dist/utils/md.js +3 -3
  46. package/dist/utils/spo.js +87 -3
  47. package/docs/docs/cmd/_global.mdx +1 -1
  48. package/docs/docs/cmd/entra/organization/organization-set.mdx +84 -0
  49. package/docs/docs/cmd/planner/bucket/bucket-add.mdx +19 -0
  50. package/docs/docs/cmd/planner/bucket/bucket-get.mdx +19 -0
  51. package/docs/docs/cmd/planner/bucket/bucket-list.mdx +19 -0
  52. package/docs/docs/cmd/planner/bucket/bucket-remove.mdx +21 -0
  53. package/docs/docs/cmd/planner/bucket/bucket-set.mdx +21 -0
  54. package/docs/docs/cmd/planner/plan/plan-add.mdx +19 -0
  55. package/docs/docs/cmd/planner/plan/plan-get.mdx +19 -0
  56. package/docs/docs/cmd/planner/plan/plan-list.mdx +19 -0
  57. package/docs/docs/cmd/planner/plan/plan-remove.mdx +21 -0
  58. package/docs/docs/cmd/planner/plan/plan-set.mdx +19 -0
  59. package/docs/docs/cmd/planner/roster/roster-add.mdx +19 -0
  60. package/docs/docs/cmd/planner/roster/roster-get.mdx +19 -0
  61. package/docs/docs/cmd/planner/roster/roster-member-add.mdx +19 -0
  62. package/docs/docs/cmd/planner/roster/roster-member-get.mdx +19 -0
  63. package/docs/docs/cmd/planner/roster/roster-member-list.mdx +19 -0
  64. package/docs/docs/cmd/planner/roster/roster-member-remove.mdx +21 -0
  65. package/docs/docs/cmd/planner/roster/roster-plan-list.mdx +19 -0
  66. package/docs/docs/cmd/planner/roster/roster-remove.mdx +21 -0
  67. package/docs/docs/cmd/planner/task/task-add.mdx +19 -0
  68. package/docs/docs/cmd/planner/task/task-checklistitem-add.mdx +19 -0
  69. package/docs/docs/cmd/planner/task/task-checklistitem-list.mdx +19 -0
  70. package/docs/docs/cmd/planner/task/task-checklistitem-remove.mdx +21 -0
  71. package/docs/docs/cmd/planner/task/task-get.mdx +27 -0
  72. package/docs/docs/cmd/planner/task/task-list.mdx +19 -0
  73. package/docs/docs/cmd/planner/task/task-reference-add.mdx +19 -0
  74. package/docs/docs/cmd/planner/task/task-reference-list.mdx +19 -0
  75. package/docs/docs/cmd/planner/task/task-reference-remove.mdx +21 -0
  76. package/docs/docs/cmd/planner/task/task-remove.mdx +21 -0
  77. package/docs/docs/cmd/planner/task/task-set.mdx +19 -0
  78. package/docs/docs/cmd/planner/tenant/tenant-settings-list.mdx +44 -7
  79. package/docs/docs/cmd/planner/tenant/tenant-settings-set.mdx +43 -8
  80. package/docs/docs/cmd/spo/list/list-view-add.mdx +53 -10
  81. package/docs/docs/cmd/spo/page/page-control-remove.mdx +56 -0
  82. package/docs/docs/cmd/spo/page/page-section-add.mdx +22 -2
  83. package/npm-shrinkwrap.json +2324 -536
  84. package/package.json +17 -14
@@ -1,12 +1,11 @@
1
1
  import { z } from 'zod';
2
2
  import { zod } from '../../../../utils/zod.js';
3
3
  import { globalOptionsZod } from '../../../../Command.js';
4
- import request from '../../../../request.js';
5
- import { formatting } from '../../../../utils/formatting.js';
6
4
  import { urlUtil } from '../../../../utils/urlUtil.js';
7
5
  import { validation } from '../../../../utils/validation.js';
8
6
  import SpoCommand from '../../../base/SpoCommand.js';
9
7
  import commands from '../../commands.js';
8
+ import { Page } from './Page.js';
10
9
  const options = globalOptionsZod
11
10
  .extend({
12
11
  webUrl: zod.alias('u', z.string()
@@ -36,14 +35,7 @@ class SpoPagePublishCommand extends SpoCommand {
36
35
  if (this.verbose) {
37
36
  await logger.logToStderr(`Publishing page ${pageName}...`);
38
37
  }
39
- const filePath = `${urlUtil.getServerRelativeSiteUrl(args.options.webUrl)}/SitePages/${pageName}`;
40
- const requestOptions = {
41
- url: `${args.options.webUrl}/_api/web/GetFileByServerRelativePath(DecodedUrl='${formatting.encodeQueryParameter(filePath)}')/Publish()`,
42
- headers: {
43
- accept: 'application/json;odata=nometadata'
44
- }
45
- };
46
- await request.post(requestOptions);
38
+ await Page.publishPage(args.options.webUrl, pageName);
47
39
  }
48
40
  catch (err) {
49
41
  this.handleRejectedODataJsonPromise(err);
@@ -11,6 +11,7 @@ import { validation } from '../../../../utils/validation.js';
11
11
  import SpoCommand from '../../../base/SpoCommand.js';
12
12
  import commands from '../../commands.js';
13
13
  import { CanvasSectionTemplate } from './clientsidepages.js';
14
+ import { Page } from './Page.js';
14
15
  class SpoPageSectionAddCommand extends SpoCommand {
15
16
  get name() {
16
17
  return commands.PAGE_SECTION_ADD;
@@ -21,10 +22,12 @@ class SpoPageSectionAddCommand extends SpoCommand {
21
22
  constructor() {
22
23
  super();
23
24
  _SpoPageSectionAddCommand_instances.add(this);
24
- this.sectionTemplate = ['OneColumn', 'OneColumnFullWidth', 'TwoColumn', 'ThreeColumn', 'TwoColumnLeft', 'TwoColumnRight', 'Vertical'];
25
+ this.sectionTemplate = ['OneColumn', 'OneColumnFullWidth', 'TwoColumn', 'ThreeColumn', 'TwoColumnLeft', 'TwoColumnRight', 'Vertical', 'Flexible'];
25
26
  this.zoneEmphasis = ['None', 'Neutral', 'Soft', 'Strong', 'Image', 'Gradient'];
26
27
  this.iconAlignment = ['Left', 'Right'];
27
28
  this.fillMode = ['ScaleToFill', 'ScaleToFit', 'Tile', 'OriginalSize'];
29
+ this.zoneReflowStrategy = ['TopToBottom', 'LeftToRight'];
30
+ this.MINIMUM_ZONE_HEIGHT = 34;
28
31
  __classPrivateFieldGet(this, _SpoPageSectionAddCommand_instances, "m", _SpoPageSectionAddCommand_initTelemetry).call(this);
29
32
  __classPrivateFieldGet(this, _SpoPageSectionAddCommand_instances, "m", _SpoPageSectionAddCommand_initOptions).call(this);
30
33
  __classPrivateFieldGet(this, _SpoPageSectionAddCommand_instances, "m", _SpoPageSectionAddCommand_initValidators).call(this);
@@ -49,15 +52,14 @@ class SpoPageSectionAddCommand extends SpoCommand {
49
52
  };
50
53
  const res = await request.get(requestOptions);
51
54
  canvasContent = JSON.parse(res.CanvasContent1 || "[{\"controlType\":0,\"pageSettingsSlice\":{\"isDefaultDescription\":true,\"isDefaultThumbnail\":true}}]");
55
+ if (args.options.sectionTemplate === 'OneColumnFullWidth') {
56
+ this.ensureFullWidthSectionCanBeAdded(canvasContent);
57
+ }
58
+ if (args.options.sectionTemplate === 'Vertical') {
59
+ this.ensureVerticalSectionCanBeAdded(canvasContent);
60
+ }
52
61
  if (!res.IsPageCheckedOutToCurrentUser) {
53
- requestOptions = {
54
- url: `${args.options.webUrl}/_api/sitepages/pages/GetByUrl('sitepages/${formatting.encodeQueryParameter(pageFullName)}')/checkoutpage`,
55
- headers: {
56
- 'accept': 'application/json;odata=nometadata'
57
- },
58
- responseType: 'json'
59
- };
60
- await request.post(requestOptions);
62
+ await Page.checkout(pageFullName, args.options.webUrl, logger, this.verbose);
61
63
  }
62
64
  // get unique zoneIndex values given each section can have 1 or more
63
65
  // columns each assigned to the zoneIndex of the corresponding section
@@ -148,6 +150,9 @@ class SpoPageSectionAddCommand extends SpoCommand {
148
150
  case 'Vertical':
149
151
  columns.push(this.getVerticalColumn(args, zoneId));
150
152
  break;
153
+ case 'Flexible':
154
+ columns.push(this.getFlexibleColumn(zoneIndex, sectionIndex++, args, zoneId));
155
+ break;
151
156
  case 'OneColumn':
152
157
  default:
153
158
  columns.push(this.getColumn(zoneIndex, sectionIndex++, 12, args, zoneId));
@@ -168,9 +173,9 @@ class SpoPageSectionAddCommand extends SpoCommand {
168
173
  },
169
174
  emphasis: {}
170
175
  };
171
- if (zoneEmphasis && ['none', 'neutral', 'soft', 'strong'].includes(zoneEmphasis?.toLocaleLowerCase())) {
176
+ if (zoneEmphasis && ['none', 'neutral', 'soft', 'strong'].includes(zoneEmphasis?.toLowerCase())) {
172
177
  // Just these zoneEmphasis values should be added to column emphasis
173
- const zoneEmphasisValue = ['none', 'neutral', 'soft', 'strong'].indexOf(zoneEmphasis.toLocaleLowerCase());
178
+ const zoneEmphasisValue = ['none', 'neutral', 'soft', 'strong'].indexOf(zoneEmphasis.toLowerCase());
174
179
  columnValue.emphasis = { zoneEmphasis: zoneEmphasisValue };
175
180
  }
176
181
  if (isCollapsibleSection) {
@@ -178,8 +183,9 @@ class SpoPageSectionAddCommand extends SpoCommand {
178
183
  type: 1,
179
184
  isExpanded: !!isExpanded,
180
185
  showDividerLine: !!showDivider,
181
- iconAlignment: iconAlignment && iconAlignment.toLocaleLowerCase() === "right" ? "right" : "left",
182
- displayName: collapsibleTitle
186
+ iconAlignment: iconAlignment && iconAlignment.toLowerCase() === "right" ? "right" : "left",
187
+ displayName: collapsibleTitle,
188
+ headingLevel: args.options.headingLevel ? args.options.headingLevel : 2 //2 is a default heading level
183
189
  };
184
190
  }
185
191
  return columnValue;
@@ -191,6 +197,14 @@ class SpoPageSectionAddCommand extends SpoCommand {
191
197
  columnValue.position.controlIndex = 1;
192
198
  return columnValue;
193
199
  }
200
+ getFlexibleColumn(zoneIndex, sectionIndex, args, zoneId) {
201
+ const columnValue = this.getColumn(zoneIndex, sectionIndex, 100, args, zoneId);
202
+ columnValue.zoneReflowStrategy = { axis: args.options.zoneReflowStrategy ? this.zoneReflowStrategy.indexOf(args.options.zoneReflowStrategy) : 0 };
203
+ if (args.options.zoneHeight) {
204
+ columnValue.zoneHeight = args.options.zoneHeight;
205
+ }
206
+ return columnValue;
207
+ }
194
208
  setBackgroundControl(zoneId, backgroundControl, args) {
195
209
  const { overlayColor, overlayOpacity, useLightText, imageUrl } = args.options;
196
210
  const backgroundDetails = this.getBackgroundDetails(args);
@@ -243,6 +257,18 @@ class SpoPageSectionAddCommand extends SpoCommand {
243
257
  }
244
258
  return backgroundDetails;
245
259
  }
260
+ ensureFullWidthSectionCanBeAdded(canvasContent) {
261
+ const hasVerticalSection = canvasContent.some((c) => c.position?.layoutIndex === 2 && c.position.sectionFactor === 12);
262
+ if (hasVerticalSection) {
263
+ throw "A vertical section already exists on the page. A full-width section cannot be added to a page that already has a vertical section.";
264
+ }
265
+ }
266
+ ensureVerticalSectionCanBeAdded(canvasContent) {
267
+ const hasFullWidthSection = canvasContent.some((c) => c.position?.layoutIndex === 1 && c.position.sectionFactor === 0);
268
+ if (hasFullWidthSection) {
269
+ throw "A full-width section already exists on the page. A vertical section cannot be added to a page that already has a full-width section.";
270
+ }
271
+ }
246
272
  }
247
273
  _SpoPageSectionAddCommand_instances = new WeakSet(), _SpoPageSectionAddCommand_initTelemetry = function _SpoPageSectionAddCommand_initTelemetry() {
248
274
  this.telemetry.push((args) => {
@@ -262,7 +288,10 @@ _SpoPageSectionAddCommand_instances = new WeakSet(), _SpoPageSectionAddCommand_i
262
288
  useLightText: !!args.options.useLightText,
263
289
  overlayColor: typeof args.options.overlayColor !== 'undefined',
264
290
  overlayOpacity: typeof args.options.overlayOpacity !== 'undefined',
265
- collapsibleTitle: typeof args.options.collapsibleTitle !== 'undefined'
291
+ collapsibleTitle: typeof args.options.collapsibleTitle !== 'undefined',
292
+ zoneReflowStrategy: typeof args.options.zoneReflowStrategy !== 'undefined',
293
+ zoneHeight: typeof args.options.zoneHeight !== 'undefined',
294
+ headingLevel: typeof args.options.headingLevel !== 'undefined'
266
295
  });
267
296
  });
268
297
  }, _SpoPageSectionAddCommand_initOptions = function _SpoPageSectionAddCommand_initOptions() {
@@ -308,11 +337,18 @@ _SpoPageSectionAddCommand_instances = new WeakSet(), _SpoPageSectionAddCommand_i
308
337
  option: '--overlayOpacity [overlayOpacity]'
309
338
  }, {
310
339
  option: '--collapsibleTitle [collapsibleTitle]'
340
+ }, {
341
+ option: '--zoneReflowStrategy [zoneReflowStrategy]',
342
+ autocomplete: this.zoneReflowStrategy
343
+ }, {
344
+ option: '--zoneHeight [zoneHeight]'
345
+ }, {
346
+ option: '--headingLevel [headingLevel]'
311
347
  });
312
348
  }, _SpoPageSectionAddCommand_initValidators = function _SpoPageSectionAddCommand_initValidators() {
313
349
  this.validators.push(async (args) => {
314
350
  if (!(args.options.sectionTemplate in CanvasSectionTemplate)) {
315
- return `${args.options.sectionTemplate} is not a valid section template. Allowed values are OneColumn|OneColumnFullWidth|TwoColumn|ThreeColumn|TwoColumnLeft|TwoColumnRight|Vertical`;
351
+ return `${args.options.sectionTemplate} is not a valid section template. Allowed values are OneColumn|OneColumnFullWidth|TwoColumn|ThreeColumn|TwoColumnLeft|TwoColumnRight|Vertical|Flexible`;
316
352
  }
317
353
  if (typeof args.options.order !== 'undefined') {
318
354
  if (!Number.isInteger(args.options.order) || args.options.order < 1) {
@@ -320,7 +356,7 @@ _SpoPageSectionAddCommand_instances = new WeakSet(), _SpoPageSectionAddCommand_i
320
356
  }
321
357
  }
322
358
  if (typeof args.options.zoneEmphasis !== 'undefined') {
323
- if (!this.zoneEmphasis.some(zoneEmphasisValue => zoneEmphasisValue.toLocaleLowerCase() === args.options.zoneEmphasis?.toLowerCase())) {
359
+ if (!this.zoneEmphasis.some(zoneEmphasisValue => zoneEmphasisValue.toLowerCase() === args.options.zoneEmphasis?.toLowerCase())) {
324
360
  return `The value of parameter zoneEmphasis must be ${this.zoneEmphasis.join(', ')}`;
325
361
  }
326
362
  }
@@ -330,20 +366,30 @@ _SpoPageSectionAddCommand_instances = new WeakSet(), _SpoPageSectionAddCommand_i
330
366
  }
331
367
  }
332
368
  if (typeof args.options.iconAlignment !== 'undefined') {
333
- if (!this.iconAlignment.some(iconAlignmentValue => iconAlignmentValue.toLocaleLowerCase() === args.options.iconAlignment?.toLowerCase())) {
369
+ if (!this.iconAlignment.some(iconAlignmentValue => iconAlignmentValue.toLowerCase() === args.options.iconAlignment?.toLowerCase())) {
334
370
  return `The value of parameter iconAlignment must be ${this.iconAlignment.join(', ')}`;
335
371
  }
336
372
  }
337
373
  if (typeof args.options.fillMode !== 'undefined') {
338
- if (!this.fillMode.some(fillModeValue => fillModeValue.toLocaleLowerCase() === args.options.fillMode?.toLowerCase())) {
374
+ if (!this.fillMode.some(fillModeValue => fillModeValue.toLowerCase() === args.options.fillMode?.toLowerCase())) {
339
375
  return `The value of parameter fillMode must be ${this.fillMode.join(', ')}`;
340
376
  }
341
377
  }
342
- if (args.options.zoneEmphasis?.toLocaleLowerCase() !== 'image' && (args.options.imageUrl || args.options.imageWidth ||
378
+ if (typeof args.options.zoneReflowStrategy !== 'undefined') {
379
+ if (!this.zoneReflowStrategy.some(zoneReflowStrategyValue => zoneReflowStrategyValue.toLowerCase() === args.options.zoneReflowStrategy?.toLowerCase())) {
380
+ return `The value of parameter zoneReflowStrategy must be ${this.zoneReflowStrategy.join(', ')}`;
381
+ }
382
+ }
383
+ if (typeof args.options.headingLevel !== 'undefined') {
384
+ if (![2, 3, 4].some(headingLevelValue => headingLevelValue === args.options.headingLevel)) {
385
+ return `The value of parameter headingLevel must be 2, 3 or 4`;
386
+ }
387
+ }
388
+ if (args.options.zoneEmphasis?.toLowerCase() !== 'image' && (args.options.imageUrl || args.options.imageWidth ||
343
389
  args.options.imageHeight || args.options.fillMode)) {
344
390
  return 'Specify imageUrl, imageWidth, imageHeight or fillMode only when zoneEmphasis is set to Image';
345
391
  }
346
- if (args.options.zoneEmphasis?.toLocaleLowerCase() === 'image' && !args.options.imageUrl) {
392
+ if (args.options.zoneEmphasis?.toLowerCase() === 'image' && !args.options.imageUrl) {
347
393
  return 'Specify imageUrl when zoneEmphasis is set to Image';
348
394
  }
349
395
  if (args.options.zoneEmphasis?.toLowerCase() !== 'gradient' && args.options.gradientText) {
@@ -361,10 +407,18 @@ _SpoPageSectionAddCommand_instances = new WeakSet(), _SpoPageSectionAddCommand_i
361
407
  if (!(args.options.zoneEmphasis && ['image', 'gradient'].includes(args.options.zoneEmphasis.toLowerCase())) && (args.options.overlayColor || args.options.overlayOpacity || args.options.useLightText)) {
362
408
  return 'Specify overlayColor or overlayOpacity only when zoneEmphasis is set to Image or Gradient';
363
409
  }
410
+ if (args.options.sectionTemplate?.toLowerCase() !== 'flexible' && (args.options.zoneReflowStrategy || args.options.zoneHeight)) {
411
+ return 'Specify zoneReflowStrategy or zoneHeight only when sectionTemplate is set to Flexible';
412
+ }
413
+ if (typeof args.options.zoneHeight !== 'undefined') {
414
+ if (!Number.isInteger(args.options.zoneHeight) || args.options.zoneHeight < this.MINIMUM_ZONE_HEIGHT) {
415
+ return `The value of parameter zoneHeight must be ${this.MINIMUM_ZONE_HEIGHT} or higher`;
416
+ }
417
+ }
364
418
  return validation.isValidSharePointUrl(args.options.webUrl);
365
419
  });
366
420
  }, _SpoPageSectionAddCommand_initTypes = function _SpoPageSectionAddCommand_initTypes() {
367
- this.types.string = ['pageName', 'webUrl', 'sectionTemplate', 'zoneEmphasis', 'iconAlignment', 'gradientText', 'imageUrl', 'fillMode', 'overlayColor', 'collapsibleTitle'];
421
+ this.types.string = ['pageName', 'webUrl', 'sectionTemplate', 'zoneEmphasis', 'iconAlignment', 'gradientText', 'imageUrl', 'fillMode', 'overlayColor', 'collapsibleTitle', 'zoneReflowStrategy'];
368
422
  this.types.boolean = ['isLayoutReflowOnTop', 'isCollapsibleSection', 'showDivider', 'isExpanded', 'useLightText'];
369
423
  };
370
424
  export default new SpoPageSectionAddCommand();
@@ -52,7 +52,7 @@ class SpoPageSetCommand extends SpoCommand {
52
52
  try {
53
53
  const requestDigestResult = await spo.getRequestDigest(args.options.webUrl);
54
54
  const requestDigest = requestDigestResult.FormDigestValue;
55
- const page = await Page.checkout(args.options.name, args.options.webUrl, logger, this.debug, this.verbose);
55
+ const page = await Page.checkout(args.options.name, args.options.webUrl, logger, this.verbose);
56
56
  if (page) {
57
57
  pageTitle = pageTitle || page.Title;
58
58
  pageId = page.Id;
@@ -125,7 +125,7 @@ class SpoSiteAdminAddCommand extends SpoCommand {
125
125
  const ensuredUserData = await this.ensureUser(args, loginNameToAdd);
126
126
  await this.setSiteAdmin(args.options.siteUrl, loginNameToAdd);
127
127
  if (args.options.primary) {
128
- const siteId = await this.getSiteId(args.options.siteUrl);
128
+ const siteId = await spo.getSiteIdBySPApi(args.options.siteUrl, logger, this.verbose);
129
129
  const previousPrimaryOwner = await this.getSiteOwnerLoginName(args.options.siteUrl);
130
130
  await this.setPrimaryOwnerLoginFromSite(logger, args.options.siteUrl, siteId, ensuredUserData);
131
131
  await this.setSiteAdmin(args.options.siteUrl, previousPrimaryOwner);
@@ -157,17 +157,6 @@ class SpoSiteAdminAddCommand extends SpoCommand {
157
157
  };
158
158
  return request.post(requestOptions);
159
159
  }
160
- async getSiteId(siteUrl) {
161
- const requestOptions = {
162
- url: `${siteUrl}/_api/site?$select=Id`,
163
- headers: {
164
- accept: 'application/json;odata=nometadata'
165
- },
166
- responseType: 'json'
167
- };
168
- const response = await request.get(requestOptions);
169
- return response.Id;
170
- }
171
160
  async getSiteOwnerLoginName(siteUrl) {
172
161
  const requestOptions = {
173
162
  url: `${siteUrl}/_api/site/owner?$select=LoginName`,
@@ -62,7 +62,7 @@ class SpoSiteSetCommand extends SpoCommand {
62
62
  if (this.debug) {
63
63
  await logger.logToStderr(`Setting the site its logo...`);
64
64
  }
65
- const logoUrl = args.options.siteLogoUrl ? urlUtil.getServerRelativePath(args.options.url, args.options.siteLogoUrl) : "";
65
+ const logoUrl = args.options.siteLogoUrl ? urlUtil.getUrlRelativePath(args.options.siteLogoUrl) : "";
66
66
  const requestOptions = {
67
67
  url: `${args.options.url}/_api/siteiconmanager/setsitelogo`,
68
68
  headers: {
@@ -84,7 +84,7 @@ class SpoSiteSetCommand extends SpoCommand {
84
84
  if (this.debug) {
85
85
  await logger.logToStderr(`Setting the site thumbnail...`);
86
86
  }
87
- const thumbnailUrl = args.options.siteThumbnailUrl ? urlUtil.getServerRelativePath(args.options.url, args.options.siteThumbnailUrl) : "";
87
+ const thumbnailUrl = args.options.siteThumbnailUrl ? urlUtil.getUrlRelativePath(args.options.siteThumbnailUrl) : "";
88
88
  const requestOptions = {
89
89
  url: `${args.options.url}/_api/siteiconmanager/setsitelogo`,
90
90
  headers: {
@@ -217,6 +217,7 @@ export default {
217
217
  PAGE_COLUMN_LIST: `${prefix} page column list`,
218
218
  PAGE_CONTROL_GET: `${prefix} page control get`,
219
219
  PAGE_CONTROL_LIST: `${prefix} page control list`,
220
+ PAGE_CONTROL_REMOVE: `${prefix} page control remove`,
220
221
  PAGE_CONTROL_SET: `${prefix} page control set`,
221
222
  PAGE_HEADER_SET: `${prefix} page header set`,
222
223
  PAGE_SECTION_ADD: `${prefix} page section add`,
@@ -1,6 +1,7 @@
1
1
  import { odata } from './odata.js';
2
2
  import { formatting } from './formatting.js';
3
3
  import { cli } from '../cli/cli.js';
4
+ import request from '../request.js';
4
5
  export const entraServicePrincipal = {
5
6
  /**
6
7
  * Get service principal by its appId
@@ -52,6 +53,26 @@ export const entraServicePrincipal = {
52
53
  url += `?$select=${properties}`;
53
54
  }
54
55
  return odata.getAllItems(url);
56
+ },
57
+ /**
58
+ * Create a new service principal for the specified application.
59
+ * @param appId Application ID of the application for which to create a service principal.
60
+ * @returns The created service principal.
61
+ */
62
+ async createServicePrincipal(appId) {
63
+ const url = `https://graph.microsoft.com/v1.0/servicePrincipals`;
64
+ const requestOptions = {
65
+ url: url,
66
+ headers: {
67
+ accept: 'application/json;odata.metadata=none',
68
+ 'content-type': 'application/json;odata=nometadata'
69
+ },
70
+ data: {
71
+ appId
72
+ },
73
+ responseType: 'json'
74
+ };
75
+ return await request.post(requestOptions);
55
76
  }
56
77
  };
57
78
  //# sourceMappingURL=entraServicePrincipal.js.map
package/dist/utils/md.js CHANGED
@@ -13,8 +13,8 @@ function convertHeadings(md) {
13
13
  });
14
14
  }
15
15
  function convertAdmonitions(md) {
16
- const regex = new RegExp(/^:::(\w+)(?:\[([^\]]+)\])?([\s\S]*?):::$/, 'gm');
17
- return md.replace(regex, (_, label, title, content) => label.toLocaleUpperCase() + (title ? EOL + EOL + title : '') + EOL + EOL + content.trim());
16
+ const regex = new RegExp(/^([ \t]*):::(\w+)(?:\[([^\]]+)\])?([\s\S]*?)^\1:::$/, 'gm');
17
+ return md.replace(regex, (_, indent, label, title, content) => indent + label.toLocaleUpperCase() + (title ? EOL + EOL + indent + title : '') + EOL + EOL + indent + content.trim());
18
18
  }
19
19
  function includeContent(md, rootFolder) {
20
20
  const mdxImports = [
@@ -49,7 +49,7 @@ function convertHyperlinks(md) {
49
49
  function convertContentTabs(md) {
50
50
  return md
51
51
  .replace(/<TabItem value="([^"]+)">/gm, '$1')
52
- .replace(/.*<\/?(Tabs|TabItem)>.*\n?/g, '')
52
+ .replace(/.*\n?<\/?(Tabs|TabItem)>.*\n?/g, '')
53
53
  .replace(/```(?:\w+)?\s*([\s\S]*?)\s*```/g, '$1')
54
54
  .trim();
55
55
  }
package/dist/utils/spo.js CHANGED
@@ -1403,13 +1403,13 @@ export const spo = {
1403
1403
  await request.post(requestOptions);
1404
1404
  },
1405
1405
  /**
1406
- * Retrieves the site ID for a given web URL.
1406
+ * Retrieves the site ID for a given web URL by the MS Graph.
1407
1407
  * @param webUrl The web URL for which to retrieve the site ID.
1408
1408
  * @param logger The logger object.
1409
1409
  * @param verbose Set for verbose logging
1410
- * @returns A promise that resolves to the site ID.
1410
+ * @returns The site ID as a string.
1411
1411
  */
1412
- async getSiteId(webUrl, logger, verbose) {
1412
+ async getSiteIdByMSGraph(webUrl, logger, verbose) {
1413
1413
  if (verbose && logger) {
1414
1414
  await logger.logToStderr(`Getting site id for URL: ${webUrl}...`);
1415
1415
  }
@@ -1424,6 +1424,90 @@ export const spo = {
1424
1424
  const site = await request.get(requestOptions);
1425
1425
  return site.id;
1426
1426
  },
1427
+ /**
1428
+ * Retrieves the SharePoint Online site ID for the specified web URL by the SharePoint REST API.
1429
+ * @param webUrl The web URL of the SharePoint Online site to retrieve the site ID for.
1430
+ * @param logger The logger object.
1431
+ * @param verbose Set for verbose logging
1432
+ * @returns The site ID as a string.
1433
+ */
1434
+ async getSiteIdBySPApi(webUrl, logger, verbose) {
1435
+ if (verbose && logger) {
1436
+ await logger.logToStderr(`Getting site id for URL: ${webUrl}...`);
1437
+ }
1438
+ const requestOptions = {
1439
+ url: `${webUrl}/_api/site?$select=Id`,
1440
+ headers: {
1441
+ accept: 'application/json;odata=nometadata'
1442
+ },
1443
+ responseType: 'json'
1444
+ };
1445
+ const siteResponse = await request.get(requestOptions);
1446
+ return siteResponse.Id;
1447
+ },
1448
+ /**
1449
+ * Retrieves the id of a SharePoint web for the specified web URL.
1450
+ * @param webUrl The web URL for which to retrieve the web ID.
1451
+ * @param logger The logger object for logging messages.
1452
+ * @param verbose Set to true for verbose logging.
1453
+ * @returns The web ID as a string.
1454
+ */
1455
+ async getWebId(webUrl, logger, verbose) {
1456
+ if (verbose && logger) {
1457
+ await logger.logToStderr(`Getting web id for URL: ${webUrl}...`);
1458
+ }
1459
+ const requestOptions = {
1460
+ url: `${webUrl}/_api/web?$select=Id`,
1461
+ headers: {
1462
+ accept: 'application/json;odata=nometadata'
1463
+ },
1464
+ responseType: 'json'
1465
+ };
1466
+ const webResponse = await request.get(requestOptions);
1467
+ return webResponse.Id;
1468
+ },
1469
+ /**
1470
+ * Retrieves the ID of a SharePoint list by its title or URL.
1471
+ * @param webUrl The base URL of the SharePoint site.
1472
+ * @param listTitle The title of the list (optional).
1473
+ * @param listUrl The server-relative URL of the list (optional).
1474
+ * @param logger The logger object for logging messages (optional).
1475
+ * @param verbose Set to true for verbose logging (optional).
1476
+ * @returns The list ID as a string.
1477
+ */
1478
+ async getListId(webUrl, listTitle, listUrl, logger, verbose) {
1479
+ if (verbose && logger) {
1480
+ await logger.logToStderr(`Retrieving list id...`);
1481
+ }
1482
+ if (!listTitle && !listUrl) {
1483
+ throw new Error('Either listTitle or listUrl must be provided.');
1484
+ }
1485
+ let listId = '';
1486
+ if (listTitle) {
1487
+ const requestOptions = {
1488
+ url: `${webUrl}/_api/web/lists/getByTitle('${formatting.encodeQueryParameter(listTitle)}')?$select=Id`,
1489
+ headers: {
1490
+ accept: 'application/json;odata=nometadata'
1491
+ },
1492
+ responseType: 'json'
1493
+ };
1494
+ const listResponse = await request.get(requestOptions);
1495
+ listId = listResponse.Id;
1496
+ }
1497
+ else if (listUrl) {
1498
+ const listServerRelativeUrl = urlUtil.getServerRelativePath(webUrl, listUrl);
1499
+ const requestOptions = {
1500
+ url: `${webUrl}/_api/web/GetList('${formatting.encodeQueryParameter(listServerRelativeUrl)}')?$select=Id`,
1501
+ headers: {
1502
+ accept: 'application/json;odata=nometadata'
1503
+ },
1504
+ responseType: 'json'
1505
+ };
1506
+ const listResponse = await request.get(requestOptions);
1507
+ listId = listResponse.Id;
1508
+ }
1509
+ return listId;
1510
+ },
1427
1511
  /**
1428
1512
  * Retrieves the server-relative URL of a folder.
1429
1513
  * @param webUrl Web URL
@@ -1,6 +1,6 @@
1
1
  ```md definition-list
2
2
  `-h, --help [help]`
3
- : Output usage information. Optionally, specify which section of command's help you want to see. Allowed values are `options`, `examples`, `remarks`, `response`, `full`. Default is `options`.
3
+ : Output usage information. Optionally, specify which section of command's help you want to see. Allowed values are `options`, `examples`, `remarks`, `permissions`, `response`, `full`. Default is `options`.
4
4
 
5
5
  `--query [query]`
6
6
  : JMESPath query string. See [http://jmespath.org/](http://jmespath.org/) for more information and examples.
@@ -0,0 +1,84 @@
1
+ import Global from '/docs/cmd/_global.mdx';
2
+ import Tabs from '@theme/Tabs';
3
+ import TabItem from '@theme/TabItem';
4
+
5
+ # entra organization set
6
+
7
+ Updates info about the organization
8
+
9
+ ## Usage
10
+
11
+ ```sh
12
+ m365 entra organization set [options]
13
+ ```
14
+
15
+ ## Options
16
+
17
+ ```md definition-list
18
+ `-i, --id [id]`
19
+ : The id of the organization. Specify either `id` or `displayName`, but not both.
20
+
21
+ `-d, --displayName [displayName]`
22
+ : The name of the organization. Specify either `id` or `displayName`, but not both.
23
+
24
+ `--marketingNotificationEmails [marketingNotificationEmails]`
25
+ : The comma separated list of marketing notification emails.
26
+
27
+ `--securityComplianceNotificationMails [securityComplianceNotificationMails]`
28
+ : The comma separated list of security compliance notification emails.
29
+
30
+ `--securityComplianceNotificationPhones [securityComplianceNotificationPhones]`
31
+ : The comma separated list of security compliance notification phones.
32
+
33
+ `--technicalNotificationMails [technicalNotificationMails]`
34
+ : The comma separated list of technical notification emails.
35
+
36
+ `--contactEmail [contactEmail]`
37
+ : A valid smtp email address for the privacy statement contact
38
+
39
+ `--statementUrl [statementUrl]`
40
+ : The URL that directs to the company's privacy statement
41
+ ```
42
+
43
+ <Global />
44
+
45
+ ## Permissions
46
+
47
+ <Tabs>
48
+ <TabItem value="Delegated">
49
+
50
+ | Resource | Permissions |
51
+ |-----------------|--------------------------------------------------|
52
+ | Microsoft Graph | Organization.ReadWrite.All |
53
+
54
+ </TabItem>
55
+ <TabItem value="Application">
56
+
57
+ | Resource | Permissions |
58
+ |-----------------|----------------------------------------------------------|
59
+ | Microsoft Graph | Organization.ReadWrite.All |
60
+
61
+ </TabItem>
62
+ </Tabs>
63
+
64
+ ## Examples
65
+
66
+ Updates properties of an organization specified by id
67
+
68
+ ```sh
69
+ m365 entra organization set --id 84841066-274d-4ec0-a5c1-276be684bdd3 --marketingNotificationEmails 'marketing@contoso.com'
70
+ ```
71
+
72
+ Updates properties of an organization specified by displayName
73
+
74
+ ```sh
75
+ m365 entra organization set --displayName Contoso --marketingNotificationEmails 'marketing@contoso.com'
76
+ ```
77
+
78
+ ## Response
79
+
80
+ The command won't return a response on success
81
+
82
+ ## More information
83
+
84
+ - Organization: https://learn.microsoft.com/graph/api/organization-update
@@ -47,6 +47,25 @@ When using `rosterId`, the command is based on an API that is currently in previ
47
47
 
48
48
  :::
49
49
 
50
+ ## Permissions
51
+
52
+ <Tabs>
53
+ <TabItem value="Delegated">
54
+
55
+ | Resource | Permissions |
56
+ |-----------------|---------------------------------------|
57
+ | Microsoft Graph | Tasks.ReadWrite, GroupMember.Read.All |
58
+
59
+ </TabItem>
60
+ <TabItem value="Application">
61
+
62
+ | Resource | Permissions |
63
+ |-----------------|-------------------------------------------|
64
+ | Microsoft Graph | Tasks.ReadWrite.All, GroupMember.Read.All |
65
+
66
+ </TabItem>
67
+ </Tabs>
68
+
50
69
  ## Examples
51
70
 
52
71
  Adds a Microsoft Planner bucket for a plan based on its ID with an order hint
@@ -47,6 +47,25 @@ When using `rosterId`, the command is based on an API that is currently in previ
47
47
 
48
48
  :::
49
49
 
50
+ ## Permissions
51
+
52
+ <Tabs>
53
+ <TabItem value="Delegated">
54
+
55
+ | Resource | Permissions |
56
+ |-----------------|----------------------------------|
57
+ | Microsoft Graph | Tasks.Read, GroupMember.Read.All |
58
+
59
+ </TabItem>
60
+ <TabItem value="Application">
61
+
62
+ | Resource | Permissions |
63
+ |-----------------|--------------------------------------|
64
+ | Microsoft Graph | Tasks.Read.All, GroupMember.Read.All |
65
+
66
+ </TabItem>
67
+ </Tabs>
68
+
50
69
  ## Examples
51
70
 
52
71
  Gets the specified Microsoft Planner bucket
@@ -41,6 +41,25 @@ When using `rosterId`, the command is based on an API that is currently in previ
41
41
 
42
42
  :::
43
43
 
44
+ ## Permissions
45
+
46
+ <Tabs>
47
+ <TabItem value="Delegated">
48
+
49
+ | Resource | Permissions |
50
+ |-----------------|----------------------------------|
51
+ | Microsoft Graph | Tasks.Read, GroupMember.Read.All |
52
+
53
+ </TabItem>
54
+ <TabItem value="Application">
55
+
56
+ | Resource | Permissions |
57
+ |-----------------|--------------------------------------|
58
+ | Microsoft Graph | Tasks.Read.All, GroupMember.Read.All |
59
+
60
+ </TabItem>
61
+ </Tabs>
62
+
44
63
  ## Examples
45
64
 
46
65
  Lists the Microsoft Planner buckets based on its plan ID