@pnp/cli-microsoft365 10.1.0-beta.f17d225 → 10.2.0-beta.382f561

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 (123) hide show
  1. package/.eslintrc.cjs +2 -0
  2. package/README.md +2 -2
  3. package/allCommands.json +1 -1
  4. package/allCommandsFull.json +1 -1
  5. package/dist/AuthServer.js +1 -1
  6. package/dist/Command.js +2 -2
  7. package/dist/cli/cli.js +2 -2
  8. package/dist/m365/base/AppCommand.js +5 -2
  9. package/dist/m365/commands/login.js +3 -2
  10. package/dist/m365/entra/commands/administrativeunit/administrativeunit-get.js +18 -4
  11. package/dist/m365/entra/commands/administrativeunit/administrativeunit-list.js +34 -2
  12. package/dist/m365/entra/commands/app/app-get.js +17 -5
  13. package/dist/m365/entra/commands/app/app-list.js +34 -2
  14. package/dist/m365/entra/commands/app/app-permission-remove.js +8 -1
  15. package/dist/m365/entra/commands/enterpriseapp/enterpriseapp-add.js +3 -0
  16. package/dist/m365/entra/commands/enterpriseapp/enterpriseapp-get.js +3 -0
  17. package/dist/m365/entra/commands/enterpriseapp/enterpriseapp-list.js +3 -0
  18. package/dist/m365/entra/commands/group/group-get.js +6 -3
  19. package/dist/m365/entra/commands/group/group-list.js +16 -1
  20. package/dist/m365/entra/commands/m365group/m365group-add.js +1 -1
  21. package/dist/m365/entra/commands/m365group/m365group-conversation-list.js +21 -6
  22. package/dist/m365/entra/commands/m365group/m365group-get.js +29 -7
  23. package/dist/m365/entra/commands/m365group/m365group-list.js +1 -1
  24. package/dist/m365/entra/commands/m365group/m365group-remove.js +21 -9
  25. package/dist/m365/entra/commands/m365group/m365group-renew.js +19 -7
  26. package/dist/m365/entra/commands/m365group/m365group-set.js +1 -1
  27. package/dist/m365/entra/commands/m365group/m365group-teamify.js +12 -21
  28. package/dist/m365/entra/commands/roledefinition/roledefinition-get.js +58 -0
  29. package/dist/m365/entra/commands/roledefinition/roledefinition-list.js +50 -0
  30. package/dist/m365/entra/commands/roledefinition/roledefinition-remove.js +74 -0
  31. package/dist/m365/entra/commands.js +3 -0
  32. package/dist/m365/file/commands/convert/convert-pdf.js +3 -4
  33. package/dist/m365/file/commands/file-add.js +5 -6
  34. package/dist/m365/graph/commands/subscription/subscription-add.js +46 -5
  35. package/dist/m365/pp/commands/{chatbot/chatbot-get.js → copilot/copilot-get.js} +24 -20
  36. package/dist/m365/pp/commands/{chatbot/chatbot-list.js → copilot/copilot-list.js} +16 -12
  37. package/dist/m365/pp/commands/{chatbot/chatbot-remove.js → copilot/copilot-remove.js} +28 -24
  38. package/dist/m365/pp/commands.js +3 -0
  39. package/dist/m365/spe/ContainerProperties.js +2 -0
  40. package/dist/m365/spe/commands/container/container-list.js +87 -0
  41. package/dist/m365/spe/commands/containertype/containertype-get.js +103 -0
  42. package/dist/m365/spe/commands/containertype/containertype-list.js +2 -22
  43. package/dist/m365/spe/commands.js +2 -0
  44. package/dist/m365/spfx/commands/package/package-generate.js +1 -1
  45. package/dist/m365/spfx/commands/project/JsonRule.js +2 -2
  46. package/dist/m365/spfx/commands/project/project-upgrade/rules/FN016004_TS_property_pane_property_import.js +2 -2
  47. package/dist/m365/spfx/commands/spfx-doctor.js +1 -1
  48. package/dist/m365/spo/commands/contenttype/contenttype-get.js +2 -2
  49. package/dist/m365/spo/commands/contenttype/contenttype-list.js +6 -3
  50. package/dist/m365/spo/commands/file/file-add.js +1 -1
  51. package/dist/m365/spo/commands/file/file-retentionlabel-ensure.js +1 -2
  52. package/dist/m365/spo/commands/file/file-retentionlabel-remove.js +1 -2
  53. package/dist/m365/spo/commands/folder/folder-retentionlabel-ensure.js +1 -2
  54. package/dist/m365/spo/commands/folder/folder-retentionlabel-remove.js +1 -2
  55. package/dist/m365/spo/commands/list/list-contenttype-list.js +5 -2
  56. package/dist/m365/spo/commands/listitem/listitem-batch-remove.js +10 -8
  57. package/dist/m365/spo/commands/listitem/listitem-batch-set.js +1 -1
  58. package/dist/m365/spo/commands/listitem/listitem-retentionlabel-ensure.js +1 -2
  59. package/dist/m365/spo/commands/listitem/listitem-retentionlabel-remove.js +1 -2
  60. package/dist/m365/spo/commands/page/page-add.js +1 -1
  61. package/dist/m365/spo/commands/site/site-admin-add.js +4 -12
  62. package/dist/m365/spo/commands/site/site-admin-list.js +3 -11
  63. package/dist/m365/spo/commands/site/site-admin-remove.js +4 -12
  64. package/dist/m365/spo/commands/site/site-set.js +1 -1
  65. package/dist/m365/spp/commands/model/model-remove.js +105 -0
  66. package/dist/m365/spp/commands.js +2 -1
  67. package/dist/m365/teams/commands/user/user-app-list.js +1 -1
  68. package/dist/m365/tenant/commands/people/people-pronouns-get.js +32 -0
  69. package/dist/m365/tenant/commands/report/report-office365activationcounts.js +2 -8
  70. package/dist/m365/tenant/commands/report/report-office365activationsusercounts.js +2 -8
  71. package/dist/m365/tenant/commands/report/report-office365activationsuserdetail.js +2 -8
  72. package/dist/m365/tenant/commands.js +1 -0
  73. package/dist/m365/todo/commands/list/list-remove.js +2 -1
  74. package/dist/m365/todo/commands/list/list-set.js +2 -1
  75. package/dist/m365/todo/commands/task/task-add.js +2 -1
  76. package/dist/m365/todo/commands/task/task-get.js +2 -1
  77. package/dist/m365/todo/commands/task/task-list.js +2 -1
  78. package/dist/m365/todo/commands/task/task-remove.js +2 -1
  79. package/dist/m365/todo/commands/task/task-set.js +1 -1
  80. package/dist/m365/viva/commands/engage/engage-community-set.js +111 -0
  81. package/dist/m365/viva/commands.js +1 -0
  82. package/dist/utils/entraAdministrativeUnit.js +14 -2
  83. package/dist/utils/entraGroup.js +49 -6
  84. package/dist/utils/formatting.js +8 -20
  85. package/dist/utils/roleDefinition.js +30 -3
  86. package/dist/utils/spo.js +23 -4
  87. package/dist/utils/spp.js +3 -3
  88. package/dist/utils/urlUtil.js +11 -14
  89. package/docs/docs/cmd/entra/administrativeunit/administrativeunit-get.mdx +10 -3
  90. package/docs/docs/cmd/entra/administrativeunit/administrativeunit-list.mdx +16 -1
  91. package/docs/docs/cmd/entra/app/app-get.mdx +13 -8
  92. package/docs/docs/cmd/entra/app/app-list.mdx +16 -1
  93. package/docs/docs/cmd/entra/group/group-get.mdx +10 -3
  94. package/docs/docs/cmd/entra/group/group-list.mdx +9 -2
  95. package/docs/docs/cmd/entra/m365group/m365group-conversation-list.mdx +12 -3
  96. package/docs/docs/cmd/entra/m365group/m365group-get.mdx +29 -5
  97. package/docs/docs/cmd/entra/m365group/m365group-remove.mdx +7 -4
  98. package/docs/docs/cmd/entra/m365group/m365group-renew.mdx +11 -2
  99. package/docs/docs/cmd/entra/m365group/m365group-teamify.mdx +12 -3
  100. package/docs/docs/cmd/entra/m365group/m365group-user-add.mdx +2 -2
  101. package/docs/docs/cmd/entra/m365group/m365group-user-list.mdx +6 -0
  102. package/docs/docs/cmd/entra/m365group/m365group-user-remove.mdx +1 -1
  103. package/docs/docs/cmd/entra/m365group/m365group-user-set.mdx +3 -3
  104. package/docs/docs/cmd/entra/roledefinition/roledefinition-get.mdx +150 -0
  105. package/docs/docs/cmd/entra/roledefinition/roledefinition-list.mdx +148 -0
  106. package/docs/docs/cmd/entra/roledefinition/roledefinition-remove.mdx +52 -0
  107. package/docs/docs/cmd/graph/subscription/subscription-add.mdx +30 -5
  108. package/docs/docs/cmd/login.mdx +45 -44
  109. package/docs/docs/cmd/pp/{chatbot/chatbot-get.mdx → copilot/copilot-get.mdx} +24 -18
  110. package/docs/docs/cmd/pp/{chatbot/chatbot-list.mdx → copilot/copilot-list.mdx} +20 -14
  111. package/docs/docs/cmd/pp/{chatbot/chatbot-remove.mdx → copilot/copilot-remove.mdx} +16 -10
  112. package/docs/docs/cmd/pp/managementapp/managementapp-add.mdx +1 -1
  113. package/docs/docs/cmd/spe/container/container-list.mdx +97 -0
  114. package/docs/docs/cmd/spe/containertype/containertype-get.mdx +114 -0
  115. package/docs/docs/cmd/spo/contenttype/contenttype-get.mdx +7 -1
  116. package/docs/docs/cmd/spo/contenttype/contenttype-list.mdx +7 -1
  117. package/docs/docs/cmd/spo/list/list-contenttype-list.mdx +7 -1
  118. package/docs/docs/cmd/spp/model/model-remove.mdx +57 -0
  119. package/docs/docs/cmd/tenant/people/people-pronouns-get.mdx +71 -0
  120. package/docs/docs/cmd/viva/engage/engage-community-set.mdx +61 -0
  121. package/npm-shrinkwrap.json +8 -2
  122. package/package.json +4 -2
  123. package/dist/m365/spe/ContainerTypeProperties.js +0 -2
@@ -5,6 +5,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
5
5
  };
6
6
  var _TodoListSetCommand_instances, _TodoListSetCommand_initTelemetry, _TodoListSetCommand_initOptions, _TodoListSetCommand_initOptionSets;
7
7
  import request from '../../../../request.js';
8
+ import { formatting } from '../../../../utils/formatting.js';
8
9
  import DelegatedGraphCommand from '../../../base/DelegatedGraphCommand.js';
9
10
  import commands from '../../commands.js';
10
11
  class TodoListSetCommand extends DelegatedGraphCommand {
@@ -52,7 +53,7 @@ class TodoListSetCommand extends DelegatedGraphCommand {
52
53
  return args.options.id;
53
54
  }
54
55
  const requestOptions = {
55
- url: `${endpoint}/me/todo/lists?$filter=displayName eq '${escape(args.options.name)}'`,
56
+ url: `${endpoint}/me/todo/lists?$filter=displayName eq '${formatting.encodeQueryParameter(args.options.name)}'`,
56
57
  headers: {
57
58
  accept: "application/json;odata.metadata=none"
58
59
  },
@@ -5,6 +5,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
5
5
  };
6
6
  var _TodoTaskAddCommand_instances, _a, _TodoTaskAddCommand_initTelemetry, _TodoTaskAddCommand_initOptions, _TodoTaskAddCommand_initValidators, _TodoTaskAddCommand_initOptionSets;
7
7
  import request from '../../../../request.js';
8
+ import { formatting } from '../../../../utils/formatting.js';
8
9
  import { validation } from '../../../../utils/validation.js';
9
10
  import DelegatedGraphCommand from '../../../base/DelegatedGraphCommand.js';
10
11
  import commands from '../../commands.js';
@@ -71,7 +72,7 @@ class TodoTaskAddCommand extends DelegatedGraphCommand {
71
72
  return args.options.listId;
72
73
  }
73
74
  const requestOptions = {
74
- url: `${this.resource}/v1.0/me/todo/lists?$filter=displayName eq '${escape(args.options.listName)}'`,
75
+ url: `${this.resource}/v1.0/me/todo/lists?$filter=displayName eq '${formatting.encodeQueryParameter(args.options.listName)}'`,
75
76
  headers: {
76
77
  accept: 'application/json;odata.metadata=none'
77
78
  },
@@ -6,6 +6,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
6
6
  var _TodoTaskGetCommand_instances, _TodoTaskGetCommand_initTelemetry, _TodoTaskGetCommand_initOptions, _TodoTaskGetCommand_initOptionSets;
7
7
  import { cli } from '../../../../cli/cli.js';
8
8
  import request from '../../../../request.js';
9
+ import { formatting } from '../../../../utils/formatting.js';
9
10
  import DelegatedGraphCommand from '../../../base/DelegatedGraphCommand.js';
10
11
  import commands from '../../commands.js';
11
12
  class TodoTaskGetCommand extends DelegatedGraphCommand {
@@ -30,7 +31,7 @@ class TodoTaskGetCommand extends DelegatedGraphCommand {
30
31
  return args.options.listId;
31
32
  }
32
33
  const requestOptions = {
33
- url: `${this.resource}/v1.0/me/todo/lists?$filter=displayName eq '${escape(args.options.listName)}'`,
34
+ url: `${this.resource}/v1.0/me/todo/lists?$filter=displayName eq '${formatting.encodeQueryParameter(args.options.listName)}'`,
34
35
  headers: {
35
36
  accept: 'application/json;odata.metadata=none'
36
37
  },
@@ -6,6 +6,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
6
6
  var _TodoTaskListCommand_instances, _TodoTaskListCommand_initTelemetry, _TodoTaskListCommand_initOptions, _TodoTaskListCommand_initOptionSets;
7
7
  import { cli } from '../../../../cli/cli.js';
8
8
  import request from '../../../../request.js';
9
+ import { formatting } from '../../../../utils/formatting.js';
9
10
  import { odata } from '../../../../utils/odata.js';
10
11
  import DelegatedGraphCommand from '../../../base/DelegatedGraphCommand.js';
11
12
  import commands from '../../commands.js';
@@ -31,7 +32,7 @@ class TodoTaskListCommand extends DelegatedGraphCommand {
31
32
  return args.options.listId;
32
33
  }
33
34
  const requestOptions = {
34
- url: `${this.resource}/v1.0/me/todo/lists?$filter=displayName eq '${escape(args.options.listName)}'`,
35
+ url: `${this.resource}/v1.0/me/todo/lists?$filter=displayName eq '${formatting.encodeQueryParameter(args.options.listName)}'`,
35
36
  headers: {
36
37
  accept: 'application/json;odata.metadata=none'
37
38
  },
@@ -6,6 +6,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
6
6
  var _TodoTaskRemoveCommand_instances, _TodoTaskRemoveCommand_initTelemetry, _TodoTaskRemoveCommand_initOptions, _TodoTaskRemoveCommand_initOptionSets;
7
7
  import { cli } from '../../../../cli/cli.js';
8
8
  import request from '../../../../request.js';
9
+ import { formatting } from '../../../../utils/formatting.js';
9
10
  import DelegatedGraphCommand from '../../../base/DelegatedGraphCommand.js';
10
11
  import commands from '../../commands.js';
11
12
  class TodoTaskRemoveCommand extends DelegatedGraphCommand {
@@ -37,7 +38,7 @@ class TodoTaskRemoveCommand extends DelegatedGraphCommand {
37
38
  if (options.listName) {
38
39
  // Search list by its name
39
40
  const requestOptions = {
40
- url: `${this.resource}/v1.0/me/todo/lists?$filter=displayName eq '${escape(options.listName)}'`,
41
+ url: `${this.resource}/v1.0/me/todo/lists?$filter=displayName eq '${formatting.encodeQueryParameter(options.listName)}'`,
41
42
  headers: {
42
43
  accept: "application/json;odata.metadata=none"
43
44
  },
@@ -50,7 +50,7 @@ class TodoTaskSetCommand extends DelegatedGraphCommand {
50
50
  return options.listId;
51
51
  }
52
52
  const requestOptions = {
53
- url: `${this.resource}/v1.0/me/todo/lists?$filter=displayName eq '${escape(options.listName)}'`,
53
+ url: `${this.resource}/v1.0/me/todo/lists?$filter=displayName eq '${formatting.encodeQueryParameter(options.listName)}'`,
54
54
  headers: {
55
55
  accept: 'application/json;odata.metadata=none'
56
56
  },
@@ -0,0 +1,111 @@
1
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
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
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
+ };
6
+ var _VivaEngageCommunitySetCommand_instances, _VivaEngageCommunitySetCommand_initTelemetry, _VivaEngageCommunitySetCommand_initOptions, _VivaEngageCommunitySetCommand_initValidators, _VivaEngageCommunitySetCommand_initTypes, _VivaEngageCommunitySetCommand_initOptionSets;
7
+ import request from '../../../../request.js';
8
+ import { validation } from '../../../../utils/validation.js';
9
+ import { vivaEngage } from '../../../../utils/vivaEngage.js';
10
+ import GraphCommand from '../../../base/GraphCommand.js';
11
+ import commands from '../../commands.js';
12
+ class VivaEngageCommunitySetCommand extends GraphCommand {
13
+ get name() {
14
+ return commands.ENGAGE_COMMUNITY_SET;
15
+ }
16
+ get description() {
17
+ return 'Updates an existing Viva Engage community';
18
+ }
19
+ constructor() {
20
+ super();
21
+ _VivaEngageCommunitySetCommand_instances.add(this);
22
+ this.privacyOptions = ['public', 'private'];
23
+ __classPrivateFieldGet(this, _VivaEngageCommunitySetCommand_instances, "m", _VivaEngageCommunitySetCommand_initTelemetry).call(this);
24
+ __classPrivateFieldGet(this, _VivaEngageCommunitySetCommand_instances, "m", _VivaEngageCommunitySetCommand_initOptions).call(this);
25
+ __classPrivateFieldGet(this, _VivaEngageCommunitySetCommand_instances, "m", _VivaEngageCommunitySetCommand_initValidators).call(this);
26
+ __classPrivateFieldGet(this, _VivaEngageCommunitySetCommand_instances, "m", _VivaEngageCommunitySetCommand_initTypes).call(this);
27
+ __classPrivateFieldGet(this, _VivaEngageCommunitySetCommand_instances, "m", _VivaEngageCommunitySetCommand_initOptionSets).call(this);
28
+ }
29
+ async commandAction(logger, args) {
30
+ let communityId = args.options.id;
31
+ if (args.options.displayName) {
32
+ communityId = (await vivaEngage.getCommunityByDisplayName(args.options.displayName, ['id'])).id;
33
+ }
34
+ else if (args.options.entraGroupId) {
35
+ communityId = (await vivaEngage.getCommunityByEntraGroupId(args.options.entraGroupId, ['id'])).id;
36
+ }
37
+ if (this.verbose) {
38
+ await logger.logToStderr(`Updating Viva Engage community with ID ${communityId}...`);
39
+ }
40
+ const requestOptions = {
41
+ url: `${this.resource}/v1.0/employeeExperience/communities/${communityId}`,
42
+ headers: {
43
+ accept: 'application/json;odata.metadata=none'
44
+ },
45
+ responseType: 'json',
46
+ data: {
47
+ description: args.options.description,
48
+ displayName: args.options.newDisplayName,
49
+ privacy: args.options.privacy
50
+ }
51
+ };
52
+ try {
53
+ await request.patch(requestOptions);
54
+ }
55
+ catch (err) {
56
+ this.handleRejectedODataJsonPromise(err);
57
+ }
58
+ }
59
+ }
60
+ _VivaEngageCommunitySetCommand_instances = new WeakSet(), _VivaEngageCommunitySetCommand_initTelemetry = function _VivaEngageCommunitySetCommand_initTelemetry() {
61
+ this.telemetry.push((args) => {
62
+ Object.assign(this.telemetryProperties, {
63
+ id: typeof args.options.id !== 'undefined',
64
+ displayName: typeof args.options.displayName !== 'undefined',
65
+ entraGroupId: typeof args.options.entraGroupId !== 'undefined',
66
+ newDisplayName: typeof args.options.newDisplayName !== 'undefined',
67
+ description: typeof args.options.description !== 'undefined',
68
+ privacy: typeof args.options.privacy !== 'undefined'
69
+ });
70
+ });
71
+ }, _VivaEngageCommunitySetCommand_initOptions = function _VivaEngageCommunitySetCommand_initOptions() {
72
+ this.options.unshift({
73
+ option: '-i, --id [id]'
74
+ }, {
75
+ option: '-d, --displayName [displayName]'
76
+ }, {
77
+ option: '--entraGroupId [entraGroupId]'
78
+ }, {
79
+ option: '--newDisplayName [newDisplayName]'
80
+ }, {
81
+ option: '--description [description]'
82
+ }, {
83
+ option: '--privacy [privacy]',
84
+ autocomplete: this.privacyOptions
85
+ });
86
+ }, _VivaEngageCommunitySetCommand_initValidators = function _VivaEngageCommunitySetCommand_initValidators() {
87
+ this.validators.push(async (args) => {
88
+ if (args.options.entraGroupId && !validation.isValidGuid(args.options.entraGroupId)) {
89
+ return `${args.options.entraGroupId} is not a valid GUID for the option 'entraGroupId'.`;
90
+ }
91
+ if (args.options.newDisplayName && args.options.newDisplayName.length > 255) {
92
+ return `The maximum amount of characters for 'newDisplayName' is 255.`;
93
+ }
94
+ if (args.options.description && args.options.description.length > 1024) {
95
+ return `The maximum amount of characters for 'description' is 1024.`;
96
+ }
97
+ if (args.options.privacy && this.privacyOptions.map(x => x.toLowerCase()).indexOf(args.options.privacy.toLowerCase()) === -1) {
98
+ return `${args.options.privacy} is not a valid privacy. Allowed values are ${this.privacyOptions.join(', ')}`;
99
+ }
100
+ if (!args.options.newDisplayName && !args.options.description && !args.options.privacy) {
101
+ return 'Specify at least newDisplayName, description, or privacy.';
102
+ }
103
+ return true;
104
+ });
105
+ }, _VivaEngageCommunitySetCommand_initTypes = function _VivaEngageCommunitySetCommand_initTypes() {
106
+ this.types.string.push('id', 'displayName', 'entraGroupId', 'newDisplayName', 'description', 'privacy');
107
+ }, _VivaEngageCommunitySetCommand_initOptionSets = function _VivaEngageCommunitySetCommand_initOptionSets() {
108
+ this.optionSets.push({ options: ['id', 'displayName', 'entraGroupId'] });
109
+ };
110
+ export default new VivaEngageCommunitySetCommand();
111
+ //# sourceMappingURL=engage-community-set.js.map
@@ -4,6 +4,7 @@ export default {
4
4
  ENGAGE_COMMUNITY_ADD: `${prefix} engage community add`,
5
5
  ENGAGE_COMMUNITY_GET: `${prefix} engage community get`,
6
6
  ENGAGE_COMMUNITY_LIST: `${prefix} engage community list`,
7
+ ENGAGE_COMMUNITY_SET: `${prefix} engage community set`,
7
8
  ENGAGE_COMMUNITY_USER_LIST: `${prefix} engage community user list`,
8
9
  ENGAGE_GROUP_LIST: `${prefix} engage group list`,
9
10
  ENGAGE_GROUP_USER_ADD: `${prefix} engage group user add`,
@@ -5,12 +5,24 @@ export const entraAdministrativeUnit = {
5
5
  /**
6
6
  * Get an administrative unit by its display name.
7
7
  * @param displayName Administrative unit display name.
8
+ * @param properties Properties to include in the response.
8
9
  * @returns The administrative unit.
9
10
  * @throws Error when administrative unit was not found.
10
11
  */
11
- async getAdministrativeUnitByDisplayName(displayName) {
12
+ async getAdministrativeUnitByDisplayName(displayName, properties) {
13
+ const queryParameters = [];
14
+ if (properties) {
15
+ const allProperties = properties.split(',');
16
+ const selectProperties = allProperties.filter(prop => !prop.includes('/'));
17
+ if (selectProperties.length > 0) {
18
+ queryParameters.push(`$select=${selectProperties}`);
19
+ }
20
+ }
21
+ const queryString = queryParameters.length > 0
22
+ ? `?${queryParameters.join('&')}`
23
+ : '';
12
24
  const graphResource = 'https://graph.microsoft.com';
13
- const administrativeUnits = await odata.getAllItems(`${graphResource}/v1.0/directory/administrativeUnits?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'`);
25
+ const administrativeUnits = await odata.getAllItems(`${graphResource}/v1.0/directory/administrativeUnits?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'${queryString}`);
14
26
  if (administrativeUnits.length === 0) {
15
27
  throw `The specified administrative unit '${displayName}' does not exist.`;
16
28
  }
@@ -7,10 +7,22 @@ export const entraGroup = {
7
7
  /**
8
8
  * Retrieve a single group.
9
9
  * @param id Group ID.
10
+ * @param properties Properties to include in the response.
10
11
  */
11
- async getGroupById(id) {
12
+ async getGroupById(id, properties) {
13
+ const queryParameters = [];
14
+ if (properties) {
15
+ const allProperties = properties.split(',');
16
+ const selectProperties = allProperties.filter(prop => !prop.includes('/'));
17
+ if (selectProperties.length > 0) {
18
+ queryParameters.push(`$select=${selectProperties}`);
19
+ }
20
+ }
21
+ const queryString = queryParameters.length > 0
22
+ ? `?${queryParameters.join('&')}`
23
+ : '';
12
24
  const requestOptions = {
13
- url: `${graphResource}/v1.0/groups/${id}`,
25
+ url: `${graphResource}/v1.0/groups/${id}${queryString}`,
14
26
  headers: {
15
27
  accept: 'application/json;odata.metadata=none'
16
28
  },
@@ -21,18 +33,31 @@ export const entraGroup = {
21
33
  /**
22
34
  * Get a list of groups by display name.
23
35
  * @param displayName Group display name.
36
+ * @param properties Properties to include in the response.
24
37
  */
25
- async getGroupsByDisplayName(displayName) {
26
- return odata.getAllItems(`${graphResource}/v1.0/groups?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'`);
38
+ async getGroupsByDisplayName(displayName, properties) {
39
+ const queryParameters = [];
40
+ if (properties) {
41
+ const allProperties = properties.split(',');
42
+ const selectProperties = allProperties.filter(prop => !prop.includes('/'));
43
+ if (selectProperties.length > 0) {
44
+ queryParameters.push(`$select=${selectProperties}`);
45
+ }
46
+ }
47
+ const queryString = queryParameters.length > 0
48
+ ? `&${queryParameters.join('&')}`
49
+ : '';
50
+ return odata.getAllItems(`${graphResource}/v1.0/groups?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'${queryString}`);
27
51
  },
28
52
  /**
29
53
  * Get a single group by its display name.
30
54
  * @param displayName Group display name.
55
+ * @param properties Properties to include in the response.
31
56
  * @throws Error when group was not found.
32
57
  * @throws Error when multiple groups with the same name were found.
33
58
  */
34
- async getGroupByDisplayName(displayName) {
35
- const groups = await this.getGroupsByDisplayName(displayName);
59
+ async getGroupByDisplayName(displayName, properties) {
60
+ const groups = await this.getGroupsByDisplayName(displayName, properties);
36
61
  if (!groups.length) {
37
62
  throw Error(`The specified group '${displayName}' does not exist.`);
38
63
  }
@@ -60,6 +85,24 @@ export const entraGroup = {
60
85
  }
61
86
  return groups[0].id;
62
87
  },
88
+ /**
89
+ * Get id of a group by its mail nickname.
90
+ * @param mailNickname Group mail nickname.
91
+ * @throws Error when group was not found.
92
+ * @throws Error when multiple groups with the same name were found.
93
+ */
94
+ async getGroupIdByMailNickname(mailNickname) {
95
+ const groups = await odata.getAllItems(`${graphResource}/v1.0/groups?$filter=mailNickname eq '${formatting.encodeQueryParameter(mailNickname)}'&$select=id`);
96
+ if (!groups.length) {
97
+ throw Error(`The specified group '${mailNickname}' does not exist.`);
98
+ }
99
+ if (groups.length > 1) {
100
+ const resultAsKeyValuePair = formatting.convertArrayToHashTable('id', groups);
101
+ const result = await cli.handleMultipleResultsFound(`Multiple groups with mail nickname '${mailNickname}' found.`, resultAsKeyValuePair);
102
+ return result.id;
103
+ }
104
+ return groups[0].id;
105
+ },
63
106
  async setGroup(id, isPrivate, logger, verbose) {
64
107
  if (verbose && logger) {
65
108
  await logger.logToStderr(`Updating Microsoft 365 Group ${id}...`);
@@ -1,3 +1,4 @@
1
+ import { parse } from 'csv-parse/sync';
1
2
  import chalk from 'chalk';
2
3
  import stripJsonComments from 'strip-json-comments';
3
4
  import { BasePermissions } from '../m365/spo/base-permissions.js';
@@ -75,26 +76,13 @@ export const formatting = {
75
76
  return response;
76
77
  },
77
78
  parseCsvToJson(s, quoteChar = '"', delimiter = ',') {
78
- const regex = new RegExp(`\\s*(${quoteChar})?(.*?)\\1\\s*(?:${delimiter}|$)`, 'gs');
79
- const lines = s.split('\n');
80
- const match = (line) => [...line.matchAll(regex)]
81
- .map(m => m[2]); // we only want the second capture group
82
- const heads = match(lines[0]).slice(0, -1);
83
- return lines.slice(1)
84
- .filter(text => text.trim() !== '')
85
- .map(line => {
86
- const lineMatch = match(line);
87
- const obj = {};
88
- heads.forEach((key, index) => {
89
- const value = parseInt(lineMatch[index]);
90
- if (isNaN(value) || value.toString() !== lineMatch[index]) {
91
- obj[key] = lineMatch[index];
92
- }
93
- else {
94
- obj[key] = parseInt(lineMatch[index]);
95
- }
96
- });
97
- return obj;
79
+ return parse(s, {
80
+ quote: quoteChar,
81
+ delimiter: delimiter,
82
+ columns: true,
83
+ skipEmptyLines: true,
84
+ ltrim: true,
85
+ cast: true
98
86
  });
99
87
  },
100
88
  encodeQueryParameter(value) {
@@ -1,15 +1,21 @@
1
1
  import { cli } from '../cli/cli.js';
2
2
  import { formatting } from './formatting.js';
3
3
  import { odata } from './odata.js';
4
+ import request from '../request.js';
4
5
  export const roleDefinition = {
5
6
  /**
6
- * Get a directory (Microsoft Entra) role
7
+ * Get an Entra ID (directory) role by its name
7
8
  * @param displayName Role definition display name.
9
+ * @param properties Comma-separated list of properties to include in the response.
8
10
  * @returns The role definition.
9
11
  * @throws Error when role definition was not found.
10
12
  */
11
- async getRoleDefinitionByDisplayName(displayName) {
12
- const roleDefinitions = await odata.getAllItems(`https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'`);
13
+ async getRoleDefinitionByDisplayName(displayName, properties) {
14
+ let url = `https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions?$filter=displayName eq '${formatting.encodeQueryParameter(displayName)}'`;
15
+ if (properties) {
16
+ url += `&$select=${properties}`;
17
+ }
18
+ const roleDefinitions = await odata.getAllItems(url);
13
19
  if (roleDefinitions.length === 0) {
14
20
  throw `The specified role definition '${displayName}' does not exist.`;
15
21
  }
@@ -19,6 +25,27 @@ export const roleDefinition = {
19
25
  return selectedRoleDefinition;
20
26
  }
21
27
  return roleDefinitions[0];
28
+ },
29
+ /**
30
+ * Get an Entra ID (directory) role by its id
31
+ * @param id Role definition id.
32
+ * @param properties Comma-separated list of properties to include in the response.
33
+ * @returns The role definition.
34
+ * @throws Error when role definition was not found.
35
+ */
36
+ async getRoleDefinitionById(id, properties) {
37
+ let url = `https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions/${id}`;
38
+ if (properties) {
39
+ url += `?$select=${properties}`;
40
+ }
41
+ const requestOptions = {
42
+ url: url,
43
+ headers: {
44
+ accept: 'application/json;odata.metadata=none'
45
+ },
46
+ responseType: 'json'
47
+ };
48
+ return await request.get(requestOptions);
22
49
  }
23
50
  };
24
51
  //# sourceMappingURL=roleDefinition.js.map
package/dist/utils/spo.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import os from 'os';
2
- import url from 'url';
3
2
  import { urlUtil } from "./urlUtil.js";
4
3
  import { validation } from "./validation.js";
5
4
  import auth from '../Auth.js';
@@ -54,6 +53,24 @@ export const spo = {
54
53
  };
55
54
  return context;
56
55
  },
56
+ async getAllContainerTypes(spoAdminUrl, logger, verbose) {
57
+ const formDigestInfo = await spo.ensureFormDigest(spoAdminUrl, logger, undefined, verbose);
58
+ const requestOptions = {
59
+ url: `${spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
60
+ headers: {
61
+ 'X-RequestDigest': formDigestInfo.FormDigestValue
62
+ },
63
+ data: `<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="${config.applicationName}" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009"><Actions><ObjectPath Id="46" ObjectPathId="45" /><Method Name="GetSPOContainerTypes" Id="47" ObjectPathId="45"><Parameters><Parameter Type="Enum">1</Parameter></Parameters></Method></Actions><ObjectPaths><Constructor Id="45" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" /></ObjectPaths></Request>`
64
+ };
65
+ const res = await request.post(requestOptions);
66
+ const json = JSON.parse(res);
67
+ const response = json[0];
68
+ if (response.ErrorInfo) {
69
+ throw new Error(response.ErrorInfo.ErrorMessage);
70
+ }
71
+ const containerTypes = json[json.length - 1];
72
+ return containerTypes;
73
+ },
57
74
  async waitUntilFinished({ operationId, siteUrl, logger, currentContext, debug, verbose }) {
58
75
  const resFormDigest = await spo.ensureFormDigest(siteUrl, logger, currentContext, debug);
59
76
  currentContext = resFormDigest;
@@ -182,8 +199,10 @@ export const spo = {
182
199
  * @param siteAccessToken a valid access token for the site specified in the webFullUrl param
183
200
  */
184
201
  async ensureFolder(webFullUrl, folderToEnsure, logger, debug) {
185
- const webUrl = url.parse(webFullUrl);
186
- if (!webUrl.protocol || !webUrl.hostname) {
202
+ try {
203
+ new URL(webFullUrl);
204
+ }
205
+ catch {
187
206
  throw new Error('webFullUrl is not a valid URL');
188
207
  }
189
208
  if (!folderToEnsure) {
@@ -1042,7 +1061,7 @@ export const spo = {
1042
1061
  headers: {
1043
1062
  'X-RequestDigest': context.FormDigestValue
1044
1063
  },
1045
- data: `<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="${config.applicationName}" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009"><Actions>${payload.join('')}<ObjectPath Id="14" ObjectPathId="13" /><ObjectIdentityQuery Id="15" ObjectPathId="5" /><Query Id="16" ObjectPathId="13"><Query SelectAllProperties="false"><Properties><Property Name="IsComplete" ScalarProperty="true" /><Property Name="PollingInterval" ScalarProperty="true" /></Properties></Query></Query></Actions><ObjectPaths><Identity Id="5" Name="53d8499e-d0d2-5000-cb83-9ade5be42ca4|${tenantId.substr(pos, tenantId.indexOf('&') - pos)}&#xA;SiteProperties&#xA;${formatting.encodeQueryParameter(url)}" /><Method Id="13" ParentId="5" Name="Update" /></ObjectPaths></Request>`
1064
+ data: `<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="${config.applicationName}" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009"><Actions>${payload.join('')}<ObjectPath Id="14" ObjectPathId="13" /><ObjectIdentityQuery Id="15" ObjectPathId="5" /><Query Id="16" ObjectPathId="13"><Query SelectAllProperties="false"><Properties><Property Name="IsComplete" ScalarProperty="true" /><Property Name="PollingInterval" ScalarProperty="true" /></Properties></Query></Query></Actions><ObjectPaths><Identity Id="5" Name="53d8499e-d0d2-5000-cb83-9ade5be42ca4|${tenantId.substring(pos, tenantId.indexOf('&'))}&#xA;SiteProperties&#xA;${formatting.encodeQueryParameter(url)}" /><Method Id="13" ParentId="5" Name="Update" /></ObjectPaths></Request>`
1046
1065
  };
1047
1066
  const res = await request.post(requestOptionsUpdateProperties);
1048
1067
  const json = JSON.parse(res);
package/dist/utils/spp.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import request from '../request.js';
2
2
  export const spp = {
3
3
  /**
4
- * Asserts whether the specified site is a content center.
5
- * @param siteUrl The URL of the site to check.
6
- * @throws Error when the site is not a content center.
4
+ * Asserts whether the specified site is a content center
5
+ * @param siteUrl The URL of the site to check
6
+ * @throws error when site is not a content center.
7
7
  */
8
8
  async assertSiteIsContentCenter(siteUrl) {
9
9
  const requestOptions = {
@@ -1,4 +1,3 @@
1
- import url from 'url';
2
1
  export const urlUtil = {
3
2
  /**
4
3
  * Returns server relative path.
@@ -15,12 +14,7 @@ export const urlUtil = {
15
14
  * urlUtil.getServerRelativePath("/sites/team1/", "/Shared Documents");
16
15
  */
17
16
  getServerRelativePath(webUrl, folderRelativePath) {
18
- const tenantUrl = `${url.parse(webUrl).protocol}//${url.parse(webUrl).hostname}`;
19
- // if webUrl is a server-relative URL then tenantUrl will resolve to null//null
20
- // in which case we should keep webUrl
21
- let webRelativePath = tenantUrl !== 'null//null' ? webUrl.substr(tenantUrl.length) : webUrl;
22
- // will be used to remove relative path from the folderRelativePath
23
- // in case the web relative url is included
17
+ let webRelativePath = this.getUrlRelativePath(webUrl);
24
18
  let relativePathToRemove = webRelativePath;
25
19
  // add '/' at 0
26
20
  if (webRelativePath[0] !== '/') {
@@ -90,11 +84,8 @@ export const urlUtil = {
90
84
  * Utils.getWebRelativePath("/sites/team1/", "/sites/team1/Shared Documents");
91
85
  */
92
86
  getWebRelativePath(webUrl, folderUrl) {
87
+ let webRelativePath = this.getUrlRelativePath(webUrl);
93
88
  let folderWebRelativePath = '';
94
- const tenantUrl = `${url.parse(webUrl).protocol}//${url.parse(webUrl).hostname}`;
95
- // if webUrl is a server-relative URL then tenantUrl will resolve to null//null
96
- // in which case we should keep webUrl
97
- let webRelativePath = tenantUrl !== 'null//null' ? webUrl.substr(tenantUrl.length) : webUrl;
98
89
  // will be used to remove relative path from the folderRelativePath
99
90
  // in case the web relative url is included
100
91
  let relativePathToRemove = webRelativePath;
@@ -140,12 +131,11 @@ export const urlUtil = {
140
131
  * urlUtil.getAbsoluteUrl("https://contoso.sharepoint.com/sites/team1/", "/sites/team1/Lists/MyList");
141
132
  */
142
133
  getAbsoluteUrl(webUrl, serverRelativeUrl) {
143
- const uri = url.parse(webUrl);
144
- const tenantUrl = `${uri.protocol}//${uri.hostname}`;
134
+ const parsedUrl = new URL(webUrl);
145
135
  if (serverRelativeUrl[0] !== '/') {
146
136
  serverRelativeUrl = `/${serverRelativeUrl}`;
147
137
  }
148
- return `${tenantUrl}${serverRelativeUrl}`;
138
+ return `${parsedUrl.origin}${serverRelativeUrl}`;
149
139
  },
150
140
  /**
151
141
  * Combines base and relative url considering any missing slashes
@@ -213,6 +203,13 @@ export const urlUtil = {
213
203
  */
214
204
  removeTrailingSlashes(url) {
215
205
  return url.replace(/\/+$/, '');
206
+ },
207
+ getUrlRelativePath(url) {
208
+ if (url.includes('://')) {
209
+ const parsedUrl = new URL(url);
210
+ return url.substring(parsedUrl.origin.length);
211
+ }
212
+ return url;
216
213
  }
217
214
  };
218
215
  //# sourceMappingURL=urlUtil.js.map
@@ -20,22 +20,29 @@ m365 entra administrativeunit get [options]
20
20
 
21
21
  `-n, --displayName [displayName]`
22
22
  : The display name of the administrative unit. Specify either `id` or `displayName` but not both.
23
+
24
+ `-p, --properties [properties]`
25
+ : Comma-separated list of properties to retrieve.
23
26
  ```
24
27
 
25
28
  <Global />
26
29
 
30
+ ## Remarks
31
+
32
+ Using the `--properties` option, you can specify a comma-separated list of administrative unit properties to retrieve from the Microsoft Graph. If you don't specify any properties, the command will output the default properties returned by Graph.
33
+
27
34
  ## Examples
28
35
 
29
- Get information about the administrative unit by its id
36
+ Get information about the administrative unit by its id.
30
37
 
31
38
  ```sh
32
39
  m365 entra administrativeunit get --id 03c4c9dc-6f0c-4c4f-a4e6-0c9ed80f54c7
33
40
  ```
34
41
 
35
- Get information about the administrative unit by its display name
42
+ Get information about the administrative unit by its display name with specified properties.
36
43
 
37
44
  ```sh
38
- m365 entra administrativeunit get --displayName 'Marketing Division'
45
+ m365 entra administrativeunit get --displayName "Marketing Division" --properties "id,displayName"
39
46
  ```
40
47
 
41
48
  ## Response
@@ -14,16 +14,31 @@ m365 entra administrativeunit list [options]
14
14
 
15
15
  ## Options
16
16
 
17
+ ```md definition-list
18
+ `-p, --properties [properties]`
19
+ : Comma-separated list of properties to retrieve.
20
+ ```
21
+
17
22
  <Global />
18
23
 
24
+ ## Remarks
25
+
26
+ Using the `--properties` option, you can specify a comma-separated list of administrative unit properties to retrieve from the Microsoft Graph. If you don't specify any properties, the command will output the default properties returned by Graph.
27
+
19
28
  ## Examples
20
29
 
21
- Retrieve a list of administrative units
30
+ Retrieve a list of administrative units.
22
31
 
23
32
  ```sh
24
33
  m365 entra administrativeunit list
25
34
  ```
26
35
 
36
+ Retrieve a list of administrative units with specified properties.
37
+
38
+ ```sh
39
+ m365 entra administrativeunit list --properties "id,displayName"
40
+ ```
41
+
27
42
  ## Response
28
43
 
29
44
  <Tabs>