@pnp/cli-microsoft365 10.9.0-beta.bc13e90 → 10.10.0-beta.3dc1bcf

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 (114) hide show
  1. package/.devcontainer/Dockerfile +1 -1
  2. package/.devproxy/api-specs/sharepoint-admin.yaml +67 -0
  3. package/.devproxy/api-specs/sharepoint.yaml +230 -0
  4. package/.devproxy/devproxyrc.json +48 -0
  5. package/.devproxy/generate-openapi-spec.json +24 -0
  6. package/.devproxy/spo-csom-types.json +54 -0
  7. package/.eslintrc.cjs +8 -0
  8. package/Dockerfile +3 -3
  9. package/allCommands.json +1 -1
  10. package/allCommandsFull.json +1 -1
  11. package/dist/cli/cli.js +1 -1
  12. package/dist/m365/entra/commands/m365group/m365group-get.js +16 -3
  13. package/dist/m365/entra/commands/m365group/m365group-list.js +7 -1
  14. package/dist/m365/entra/commands/pim/pim-role-assignment-eligibility-list.js +9 -3
  15. package/dist/m365/entra/commands/pim/pim-role-assignment-list.js +9 -3
  16. package/dist/m365/entra/commands/pim/pim-role-request-list.js +9 -3
  17. package/dist/m365/file/commands/file-copy.js +2 -2
  18. package/dist/m365/file/commands/file-move.js +1 -1
  19. package/dist/m365/flow/commands/flow-list.js +14 -7
  20. package/dist/m365/flow/commands/run/run-get.js +1 -1
  21. package/dist/m365/graph/commands/subscription/subscription-add.js +10 -3
  22. package/dist/m365/planner/commands/tenant/tenant-settings-list.js +0 -3
  23. package/dist/m365/pp/commands/solution/solution-publisher-list.js +8 -1
  24. package/dist/m365/purview/commands/threatassessment/threatassessment-get.js +9 -2
  25. package/dist/m365/spo/commands/contenttype/contenttype-add.js +3 -65
  26. package/dist/m365/spo/commands/contenttype/contenttype-field-remove.js +5 -50
  27. package/dist/m365/spo/commands/contenttype/contenttype-field-set.js +4 -48
  28. package/dist/m365/spo/commands/contenttype/contenttype-set.js +8 -58
  29. package/dist/m365/spo/commands/contenttype/contenttype-sync.js +2 -2
  30. package/dist/m365/spo/commands/file/file-move.js +8 -2
  31. package/dist/m365/spo/commands/folder/folder-sharinglink-add.js +1 -1
  32. package/dist/m365/spo/commands/folder/folder-sharinglink-clear.js +1 -1
  33. package/dist/m365/spo/commands/folder/folder-sharinglink-get.js +1 -1
  34. package/dist/m365/spo/commands/folder/folder-sharinglink-list.js +1 -1
  35. package/dist/m365/spo/commands/folder/folder-sharinglink-remove.js +1 -1
  36. package/dist/m365/spo/commands/folder/folder-sharinglink-set.js +1 -1
  37. package/dist/m365/spo/commands/hubsite/hubsite-get.js +14 -5
  38. package/dist/m365/spo/commands/hubsite/hubsite-list.js +9 -2
  39. package/dist/m365/spo/commands/listitem/listitem-batch-set.js +3 -27
  40. package/dist/m365/spo/commands/page/Page.js +16 -1
  41. package/dist/m365/spo/commands/page/clientsidepages.js +49 -17
  42. package/dist/m365/spo/commands/page/page-add.js +1 -1
  43. package/dist/m365/spo/commands/page/page-clientsidewebpart-add.js +2 -8
  44. package/dist/m365/spo/commands/page/page-control-remove.js +99 -0
  45. package/dist/m365/spo/commands/page/page-control-set.js +1 -1
  46. package/dist/m365/spo/commands/page/page-header-set.js +9 -40
  47. package/dist/m365/spo/commands/page/page-publish.js +2 -10
  48. package/dist/m365/spo/commands/page/page-section-add.js +2 -8
  49. package/dist/m365/spo/commands/page/page-set.js +1 -1
  50. package/dist/m365/spo/commands/site/site-admin-add.js +1 -12
  51. package/dist/m365/spo/commands/tenant/tenant-site-list.js +16 -5
  52. package/dist/m365/spo/commands/term/term-list.js +10 -3
  53. package/dist/m365/spo/commands.js +1 -0
  54. package/dist/m365/teams/commands/chat/chat-member-add.js +10 -4
  55. package/dist/m365/viva/commands/engage/engage-community-remove.js +99 -0
  56. package/dist/m365/viva/commands/engage/engage-network-list.js +8 -2
  57. package/dist/m365/viva/commands.js +1 -0
  58. package/dist/utils/md.js +3 -3
  59. package/dist/utils/spo.js +87 -3
  60. package/docs/docs/cmd/_global.mdx +1 -1
  61. package/docs/docs/cmd/entra/m365group/m365group-get.mdx +8 -5
  62. package/docs/docs/cmd/entra/m365group/m365group-list.mdx +14 -12
  63. package/docs/docs/cmd/entra/pim/pim-role-assignment-eligibility-list.mdx +7 -4
  64. package/docs/docs/cmd/entra/pim/pim-role-assignment-list.mdx +9 -6
  65. package/docs/docs/cmd/entra/pim/pim-role-request-list.mdx +7 -4
  66. package/docs/docs/cmd/flow/flow-list.mdx +8 -5
  67. package/docs/docs/cmd/flow/run/run-get.mdx +1 -1
  68. package/docs/docs/cmd/graph/subscription/subscription-add.mdx +6 -3
  69. package/docs/docs/cmd/planner/bucket/bucket-add.mdx +19 -0
  70. package/docs/docs/cmd/planner/bucket/bucket-get.mdx +19 -0
  71. package/docs/docs/cmd/planner/bucket/bucket-list.mdx +19 -0
  72. package/docs/docs/cmd/planner/bucket/bucket-remove.mdx +21 -0
  73. package/docs/docs/cmd/planner/bucket/bucket-set.mdx +21 -0
  74. package/docs/docs/cmd/planner/plan/plan-add.mdx +19 -0
  75. package/docs/docs/cmd/planner/plan/plan-get.mdx +19 -0
  76. package/docs/docs/cmd/planner/plan/plan-list.mdx +19 -0
  77. package/docs/docs/cmd/planner/plan/plan-remove.mdx +21 -0
  78. package/docs/docs/cmd/planner/plan/plan-set.mdx +19 -0
  79. package/docs/docs/cmd/planner/roster/roster-add.mdx +19 -0
  80. package/docs/docs/cmd/planner/roster/roster-get.mdx +19 -0
  81. package/docs/docs/cmd/planner/roster/roster-member-add.mdx +19 -0
  82. package/docs/docs/cmd/planner/roster/roster-member-get.mdx +19 -0
  83. package/docs/docs/cmd/planner/roster/roster-member-list.mdx +19 -0
  84. package/docs/docs/cmd/planner/roster/roster-member-remove.mdx +21 -0
  85. package/docs/docs/cmd/planner/roster/roster-plan-list.mdx +19 -0
  86. package/docs/docs/cmd/planner/roster/roster-remove.mdx +21 -0
  87. package/docs/docs/cmd/planner/task/task-add.mdx +19 -0
  88. package/docs/docs/cmd/planner/task/task-checklistitem-add.mdx +19 -0
  89. package/docs/docs/cmd/planner/task/task-checklistitem-list.mdx +19 -0
  90. package/docs/docs/cmd/planner/task/task-checklistitem-remove.mdx +21 -0
  91. package/docs/docs/cmd/planner/task/task-get.mdx +27 -0
  92. package/docs/docs/cmd/planner/task/task-list.mdx +19 -0
  93. package/docs/docs/cmd/planner/task/task-reference-add.mdx +19 -0
  94. package/docs/docs/cmd/planner/task/task-reference-list.mdx +19 -0
  95. package/docs/docs/cmd/planner/task/task-reference-remove.mdx +21 -0
  96. package/docs/docs/cmd/planner/task/task-remove.mdx +21 -0
  97. package/docs/docs/cmd/planner/task/task-set.mdx +19 -0
  98. package/docs/docs/cmd/planner/tenant/tenant-settings-list.mdx +44 -7
  99. package/docs/docs/cmd/planner/tenant/tenant-settings-set.mdx +43 -8
  100. package/docs/docs/cmd/pp/solution/solution-publisher-list.mdx +7 -4
  101. package/docs/docs/cmd/purview/threatassessment/threatassessment-get.mdx +7 -4
  102. package/docs/docs/cmd/spo/file/file-move.mdx +4 -1
  103. package/docs/docs/cmd/spo/hubsite/hubsite-get.mdx +6 -3
  104. package/docs/docs/cmd/spo/hubsite/hubsite-list.mdx +7 -4
  105. package/docs/docs/cmd/spo/list/list-add.mdx +1 -1
  106. package/docs/docs/cmd/spo/list/list-set.mdx +2 -2
  107. package/docs/docs/cmd/spo/page/page-control-remove.mdx +56 -0
  108. package/docs/docs/cmd/spo/tenant/tenant-site-list.mdx +10 -7
  109. package/docs/docs/cmd/spo/term/term-list.mdx +7 -4
  110. package/docs/docs/cmd/teams/chat/chat-member-add.mdx +6 -3
  111. package/docs/docs/cmd/viva/engage/engage-community-remove.mdx +61 -0
  112. package/docs/docs/cmd/viva/engage/engage-network-list.mdx +7 -4
  113. package/npm-shrinkwrap.json +112 -97
  114. package/package.json +17 -14
@@ -102,32 +102,10 @@ class SpoContentTypeFieldSetCommand extends SpoCommand {
102
102
  throw 'DONE';
103
103
  }
104
104
  if (!this.siteId) {
105
- if (this.verbose) {
106
- await logger.logToStderr(`Retrieving site collection id...`);
107
- }
108
- requestOptions = {
109
- url: `${args.options.webUrl}/_api/site?$select=Id`,
110
- headers: {
111
- accept: 'application/json;odata=nometadata'
112
- },
113
- responseType: 'json'
114
- };
115
- const site = await request.get(requestOptions);
116
- this.siteId = site.Id;
105
+ this.siteId = await spo.getSiteIdBySPApi(args.options.webUrl, logger, this.verbose);
117
106
  }
118
107
  if (!this.webId) {
119
- if (this.verbose) {
120
- await logger.logToStderr(`Retrieving site id...`);
121
- }
122
- requestOptions = {
123
- url: `${args.options.webUrl}/_api/web?$select=Id`,
124
- headers: {
125
- accept: 'application/json;odata=nometadata'
126
- },
127
- responseType: 'json'
128
- };
129
- const web = await request.get(requestOptions);
130
- this.webId = web.Id;
108
+ this.webId = await spo.getWebId(args.options.webUrl, logger, this.verbose);
131
109
  }
132
110
  if (this.verbose) {
133
111
  await logger.logToStderr(`Updating field link...`);
@@ -172,30 +150,8 @@ class SpoContentTypeFieldSetCommand extends SpoCommand {
172
150
  }
173
151
  }
174
152
  await this.updateField(xField, requiresUpdate, logger, args);
175
- if (this.verbose) {
176
- await logger.logToStderr(`Retrieving site collection id...`);
177
- }
178
- const requestOptionsSiteId = {
179
- url: `${args.options.webUrl}/_api/site?$select=Id`,
180
- headers: {
181
- accept: 'application/json;odata=nometadata'
182
- },
183
- responseType: 'json'
184
- };
185
- const resSiteId = await request.get(requestOptionsSiteId);
186
- this.siteId = resSiteId.Id;
187
- if (this.verbose) {
188
- await logger.logToStderr(`Retrieving site id...`);
189
- }
190
- const requestOptionsWebId = {
191
- url: `${args.options.webUrl}/_api/web?$select=Id`,
192
- headers: {
193
- accept: 'application/json;odata=nometadata'
194
- },
195
- responseType: 'json'
196
- };
197
- const resWebId = await request.get(requestOptionsWebId);
198
- this.webId = resWebId.Id;
153
+ this.siteId = await spo.getSiteIdBySPApi(args.options.webUrl, logger, this.verbose);
154
+ this.webId = await spo.getWebId(args.options.webUrl, logger, this.verbose);
199
155
  await this.ensureRequestDigest(args.options.webUrl, logger);
200
156
  const requestOptions = {
201
157
  url: `${args.options.webUrl}/_vti_bin/client.svc/ProcessQuery`,
@@ -7,6 +7,7 @@ var _SpoContentTypeSetCommand_instances, _SpoContentTypeSetCommand_initTelemetry
7
7
  import config from '../../../../config.js';
8
8
  import request from '../../../../request.js';
9
9
  import { formatting } from '../../../../utils/formatting.js';
10
+ import { spo } from '../../../../utils/spo.js';
10
11
  import { urlUtil } from '../../../../utils/urlUtil.js';
11
12
  import { validation } from '../../../../utils/validation.js';
12
13
  import SpoCommand from '../../../base/SpoCommand.js';
@@ -33,8 +34,8 @@ class SpoContentTypeSetCommand extends SpoCommand {
33
34
  async commandAction(logger, args) {
34
35
  try {
35
36
  const contentTypeId = await this.getContentTypeId(logger, args.options);
36
- const siteId = await this.getSiteId(logger, args.options.webUrl);
37
- const webId = await this.getWebId(logger, args.options.webUrl);
37
+ const siteId = await spo.getSiteIdBySPApi(args.options.webUrl, logger, this.verbose);
38
+ const webId = await spo.getWebId(args.options.webUrl, logger, this.verbose);
38
39
  await this.updateContentType(logger, siteId, webId, contentTypeId, args.options);
39
40
  }
40
41
  catch (err) {
@@ -80,7 +81,7 @@ class SpoContentTypeSetCommand extends SpoCommand {
80
81
  headers: {
81
82
  'Content-Type': 'text/xml'
82
83
  },
83
- data: await this.getCsomCallXmlBody(options, siteId, webId, contentTypeId)
84
+ data: await this.getCsomCallXmlBody(options, siteId, webId, contentTypeId, logger)
84
85
  };
85
86
  const res = await request.post(requestOptions);
86
87
  const json = JSON.parse(res);
@@ -89,9 +90,9 @@ class SpoContentTypeSetCommand extends SpoCommand {
89
90
  throw response.ErrorInfo.ErrorMessage;
90
91
  }
91
92
  }
92
- async getCsomCallXmlBody(options, siteId, webId, contentTypeId) {
93
+ async getCsomCallXmlBody(options, siteId, webId, contentTypeId, logger) {
93
94
  const payload = this.getRequestPayload(options);
94
- const list = await this.getListId(options);
95
+ const list = await this.getListId(options, logger);
95
96
  return `<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}</Actions><ObjectPaths><Identity Id="9" Name="fc4179a0-e0d7-5000-c38b-bc3506fbab6f|740c6a0b-85e2-48a0-a494-e0f1759d4aa7:site:${siteId}:web:${webId}${list}:contenttype:${formatting.escapeXml(contentTypeId)}" /></ObjectPaths></Request>`;
96
97
  }
97
98
  getRequestPayload(options) {
@@ -122,35 +123,7 @@ class SpoContentTypeSetCommand extends SpoCommand {
122
123
  }
123
124
  return payload.join('');
124
125
  }
125
- async getSiteId(logger, webUrl) {
126
- if (this.verbose) {
127
- await logger.logToStderr(`Retrieving site collection id...`);
128
- }
129
- const requestOptions = {
130
- url: `${webUrl}/_api/site?$select=Id`,
131
- headers: {
132
- accept: 'application/json;odata=nometadata'
133
- },
134
- responseType: 'json'
135
- };
136
- const site = await request.get(requestOptions);
137
- return site.Id;
138
- }
139
- async getWebId(logger, webUrl) {
140
- if (this.verbose) {
141
- await logger.logToStderr(`Retrieving web id...`);
142
- }
143
- const requestOptions = {
144
- url: `${webUrl}/_api/web?$select=Id`,
145
- headers: {
146
- accept: 'application/json;odata=nometadata'
147
- },
148
- responseType: 'json'
149
- };
150
- const web = await request.get(requestOptions);
151
- return web.Id;
152
- }
153
- async getListId(options) {
126
+ async getListId(options, logger) {
154
127
  if (!options.listId && !options.listTitle && !options.listUrl) {
155
128
  return '';
156
129
  }
@@ -158,30 +131,7 @@ class SpoContentTypeSetCommand extends SpoCommand {
158
131
  if (options.listId) {
159
132
  return baseString += options.listId;
160
133
  }
161
- else if (options.listTitle) {
162
- const requestOptions = {
163
- url: `${options.webUrl}/_api/web/lists/getByTitle('${formatting.encodeQueryParameter(options.listTitle)}')?$select=Id`,
164
- headers: {
165
- accept: 'application/json;odata=nometadata'
166
- },
167
- responseType: 'json'
168
- };
169
- const listResponse = await request.get(requestOptions);
170
- baseString += listResponse.Id;
171
- }
172
- else if (options.listUrl) {
173
- const listServerRelativeUrl = urlUtil.getServerRelativePath(options.webUrl, options.listUrl);
174
- const requestOptions = {
175
- url: `${options.webUrl}/_api/web/GetList('${formatting.encodeQueryParameter(listServerRelativeUrl)}')?$select=Id`,
176
- headers: {
177
- accept: 'application/json;odata=nometadata'
178
- },
179
- responseType: 'json'
180
- };
181
- const listResponse = await request.get(requestOptions);
182
- baseString += listResponse.Id;
183
- }
184
- return baseString;
134
+ return baseString += await spo.getListId(options.webUrl, options.listTitle, options.listUrl, logger, this.verbose);
185
135
  }
186
136
  }
187
137
  _SpoContentTypeSetCommand_instances = new WeakSet(), _SpoContentTypeSetCommand_initTelemetry = function _SpoContentTypeSetCommand_initTelemetry() {
@@ -33,7 +33,7 @@ class SpoContentTypeSyncCommand extends SpoCommand {
33
33
  const url = new URL(webUrl);
34
34
  const baseUrl = 'https://graph.microsoft.com/v1.0/sites/';
35
35
  try {
36
- const siteUrl = url.pathname === '/' ? url.host : await spo.getSiteId(webUrl, logger, this.verbose);
36
+ const siteUrl = url.pathname === '/' ? url.host : await spo.getSiteIdByMSGraph(webUrl, logger, this.verbose);
37
37
  const listPath = listId || listTitle || listUrl ? `/lists/${listId || listTitle || await this.getListIdByUrl(webUrl, listUrl, logger)}` : '';
38
38
  const contentTypeId = await this.getContentTypeId(baseUrl, url, args.options, logger);
39
39
  if (this.verbose) {
@@ -64,7 +64,7 @@ class SpoContentTypeSyncCommand extends SpoCommand {
64
64
  if (options.id) {
65
65
  return options.id;
66
66
  }
67
- const siteId = await spo.getSiteId(`${url.origin}/sites/contenttypehub`, logger, this.verbose);
67
+ const siteId = await spo.getSiteIdByMSGraph(`${url.origin}/sites/contenttypehub`, logger, this.verbose);
68
68
  if (this.verbose) {
69
69
  await logger.logToStderr(`Retrieving content type Id by name...`);
70
70
  }
@@ -35,6 +35,9 @@ class SpoFileMoveCommand extends SpoCommand {
35
35
  const sourceServerRelativePath = await this.getSourcePath(logger, args.options);
36
36
  const sourcePath = this.getAbsoluteUrl(args.options.webUrl, sourceServerRelativePath);
37
37
  const destinationPath = this.getAbsoluteUrl(args.options.webUrl, args.options.targetUrl);
38
+ if (args.options.includeItemPermissions) {
39
+ await this.warn(logger, `Parameter 'includeItemPermissions' is deprecated. Please use 'withItemPermissions' instead`);
40
+ }
38
41
  if (this.verbose) {
39
42
  await logger.logToStderr(`Moving file '${sourceServerRelativePath}' to '${args.options.targetUrl}'...`);
40
43
  }
@@ -46,7 +49,7 @@ class SpoFileMoveCommand extends SpoCommand {
46
49
  const copyJobResponse = await spo.createFileCopyJob(args.options.webUrl, sourcePath, destinationPath, {
47
50
  nameConflictBehavior: this.getNameConflictBehaviorValue(args.options.nameConflictBehavior),
48
51
  bypassSharedLock: !!args.options.bypassSharedLock,
49
- includeItemPermissions: !!args.options.includeItemPermissions,
52
+ includeItemPermissions: !!args.options.includeItemPermissions || !!args.options.withItemPermissions,
50
53
  newName: newName,
51
54
  operation: 'move'
52
55
  });
@@ -119,6 +122,7 @@ _SpoFileMoveCommand_instances = new WeakSet(), _SpoFileMoveCommand_initTelemetry
119
122
  newName: typeof args.options.newName !== 'undefined',
120
123
  nameConflictBehavior: typeof args.options.nameConflictBehavior !== 'undefined',
121
124
  includeItemPermissions: !!args.options.includeItemPermissions,
125
+ withItemPermissions: !!args.options.withItemPermissions,
122
126
  bypassSharedLock: !!args.options.bypassSharedLock,
123
127
  skipWait: !!args.options.skipWait
124
128
  });
@@ -139,6 +143,8 @@ _SpoFileMoveCommand_instances = new WeakSet(), _SpoFileMoveCommand_initTelemetry
139
143
  autocomplete: this.nameConflictBehaviorOptions
140
144
  }, {
141
145
  option: '--includeItemPermissions'
146
+ }, {
147
+ option: '--withItemPermissions'
142
148
  }, {
143
149
  option: '--bypassSharedLock'
144
150
  }, {
@@ -162,7 +168,7 @@ _SpoFileMoveCommand_instances = new WeakSet(), _SpoFileMoveCommand_initTelemetry
162
168
  this.optionSets.push({ options: ['sourceUrl', 'sourceId'] });
163
169
  }, _SpoFileMoveCommand_initTypes = function _SpoFileMoveCommand_initTypes() {
164
170
  this.types.string.push('webUrl', 'sourceUrl', 'sourceId', 'targetUrl', 'newName', 'nameConflictBehavior');
165
- this.types.boolean.push('includeItemPermissions', 'bypassSharedLock', 'skipWait');
171
+ this.types.boolean.push('includeItemPermissions', 'withItemPermissions', 'bypassSharedLock', 'skipWait');
166
172
  };
167
173
  export default new SpoFileMoveCommand();
168
174
  //# sourceMappingURL=file-move.js.map
@@ -38,7 +38,7 @@ class SpoFolderSharingLinkAddCommand extends SpoCommand {
38
38
  const relFolderUrl = await spo.getFolderServerRelativeUrl(args.options.webUrl, args.options.folderUrl, args.options.folderId, logger, args.options.verbose);
39
39
  const absoluteFolderUrl = urlUtil.getAbsoluteUrl(args.options.webUrl, relFolderUrl);
40
40
  const folderUrl = new URL(absoluteFolderUrl);
41
- const siteId = await spo.getSiteId(args.options.webUrl);
41
+ const siteId = await spo.getSiteIdByMSGraph(args.options.webUrl);
42
42
  const driveDetails = await drive.getDriveByUrl(siteId, folderUrl, logger, args.options.verbose);
43
43
  const itemId = await drive.getDriveItemId(driveDetails, folderUrl, logger, args.options.verbose);
44
44
  const requestOptions = {
@@ -39,7 +39,7 @@ class SpoFolderSharingLinkClearCommand extends SpoCommand {
39
39
  const relFolderUrl = await spo.getFolderServerRelativeUrl(args.options.webUrl, args.options.folderUrl, args.options.folderId, logger, args.options.verbose);
40
40
  const absoluteFolderUrl = urlUtil.getAbsoluteUrl(args.options.webUrl, relFolderUrl);
41
41
  const folderUrl = new URL(absoluteFolderUrl);
42
- const siteId = await spo.getSiteId(args.options.webUrl);
42
+ const siteId = await spo.getSiteIdByMSGraph(args.options.webUrl);
43
43
  const driveDetails = await drive.getDriveByUrl(siteId, folderUrl, logger, args.options.verbose);
44
44
  const itemId = await drive.getDriveItemId(driveDetails, folderUrl, logger, args.options.verbose);
45
45
  let requestUrl = `https://graph.microsoft.com/v1.0/drives/${driveDetails.id}/items/${itemId}/permissions?$filter=Link ne null`;
@@ -35,7 +35,7 @@ class SpoFolderSharingLinkGetCommand extends SpoCommand {
35
35
  const relFolderUrl = await spo.getFolderServerRelativeUrl(args.options.webUrl, args.options.folderUrl, args.options.folderId);
36
36
  const absoluteFolderUrl = urlUtil.getAbsoluteUrl(args.options.webUrl, relFolderUrl);
37
37
  const folderUrl = new URL(absoluteFolderUrl);
38
- const siteId = await spo.getSiteId(args.options.webUrl);
38
+ const siteId = await spo.getSiteIdByMSGraph(args.options.webUrl);
39
39
  const drive = await driveItem.getDriveByUrl(siteId, folderUrl);
40
40
  const itemId = await driveItem.getDriveItemId(drive, folderUrl);
41
41
  const requestUrl = `https://graph.microsoft.com/v1.0/drives/${drive.id}/items/${itemId}/permissions/${args.options.id}`;
@@ -40,7 +40,7 @@ class SpoFolderSharingLinkListCommand extends SpoCommand {
40
40
  const relFolderUrl = await spo.getFolderServerRelativeUrl(args.options.webUrl, args.options.folderUrl, args.options.folderId, logger, args.options.verbose);
41
41
  const absoluteFolderUrl = urlUtil.getAbsoluteUrl(args.options.webUrl, relFolderUrl);
42
42
  const folderUrl = new URL(absoluteFolderUrl);
43
- const siteId = await spo.getSiteId(args.options.webUrl);
43
+ const siteId = await spo.getSiteIdByMSGraph(args.options.webUrl);
44
44
  const driveDetails = await drive.getDriveByUrl(siteId, folderUrl, logger, args.options.verbose);
45
45
  const itemId = await drive.getDriveItemId(driveDetails, folderUrl, logger, args.options.verbose);
46
46
  let requestUrl = `https://graph.microsoft.com/v1.0/drives/${driveDetails.id}/items/${itemId}/permissions?$filter=Link ne null`;
@@ -37,7 +37,7 @@ class SpoFolderSharingLinkRemoveCommand extends SpoCommand {
37
37
  const relFolderUrl = await spo.getFolderServerRelativeUrl(args.options.webUrl, args.options.folderUrl, args.options.folderId, logger, args.options.verbose);
38
38
  const absoluteFolderUrl = urlUtil.getAbsoluteUrl(args.options.webUrl, relFolderUrl);
39
39
  const folderUrl = new URL(absoluteFolderUrl);
40
- const siteId = await spo.getSiteId(args.options.webUrl);
40
+ const siteId = await spo.getSiteIdByMSGraph(args.options.webUrl);
41
41
  const driveDetails = await drive.getDriveByUrl(siteId, folderUrl, logger, args.options.verbose);
42
42
  const itemId = await drive.getDriveItemId(driveDetails, folderUrl, logger, args.options.verbose);
43
43
  const requestOptions = {
@@ -35,7 +35,7 @@ class SpoFolderSharingLinkSetCommand extends SpoCommand {
35
35
  const relFolderUrl = await spo.getFolderServerRelativeUrl(args.options.webUrl, args.options.folderUrl, args.options.folderId, logger, args.options.verbose);
36
36
  const absoluteFolderUrl = urlUtil.getAbsoluteUrl(args.options.webUrl, relFolderUrl);
37
37
  const folderUrl = new URL(absoluteFolderUrl);
38
- const siteId = await spo.getSiteId(args.options.webUrl);
38
+ const siteId = await spo.getSiteIdByMSGraph(args.options.webUrl);
39
39
  const driveDetails = await drive.getDriveByUrl(siteId, folderUrl, logger, args.options.verbose);
40
40
  const itemId = await drive.getDriveItemId(driveDetails, folderUrl, logger, args.options.verbose);
41
41
  const requestOptions = {
@@ -29,12 +29,20 @@ class SpoHubSiteGetCommand extends SpoCommand {
29
29
  }
30
30
  async commandAction(logger, args) {
31
31
  try {
32
+ if (args.options.includeAssociatedSites) {
33
+ await this.warn(logger, `Parameter 'includeAssociatedSites' is deprecated. Please use 'withAssociatedSites' instead`);
34
+ }
32
35
  const spoUrl = await spo.getSpoUrl(logger, this.debug);
33
36
  const hubSite = args.options.id ? await this.getHubSiteById(spoUrl, args.options) : await this.getHubSite(spoUrl, args.options);
34
- if (args.options.includeAssociatedSites && (args.options.output && args.options.output !== 'json')) {
35
- throw 'includeAssociatedSites option is only allowed with json output mode';
37
+ if ((args.options.includeAssociatedSites || args.options.withAssociatedSites) && (args.options.output && args.options.output !== 'json')) {
38
+ if (args.options.includeAssociatedSites) {
39
+ throw 'includeAssociatedSites option is only allowed with json output mode';
40
+ }
41
+ else {
42
+ throw 'withAssociatedSites option is only allowed with json output mode';
43
+ }
36
44
  }
37
- if (args.options.includeAssociatedSites === true && args.options.output && !cli.shouldTrimOutput(args.options.output)) {
45
+ if ((args.options.includeAssociatedSites === true || args.options.withAssociatedSites === true) && args.options.output && !cli.shouldTrimOutput(args.options.output)) {
38
46
  const spoAdminUrl = await spo.getSpoAdminUrl(logger, this.debug);
39
47
  const associatedSitesCommandOutput = await this.getAssociatedSites(spoAdminUrl, hubSite.SiteId, logger, args);
40
48
  const associatedSites = JSON.parse(associatedSitesCommandOutput.stdout);
@@ -100,11 +108,12 @@ _SpoHubSiteGetCommand_instances = new WeakSet(), _SpoHubSiteGetCommand_initTelem
100
108
  id: typeof args.options.id !== 'undefined',
101
109
  title: typeof args.options.title !== 'undefined',
102
110
  url: typeof args.options.url !== 'undefined',
103
- includeAssociatedSites: args.options.includeAssociatedSites === true
111
+ includeAssociatedSites: args.options.includeAssociatedSites === true,
112
+ withAssociatedSites: args.options.withAssociatedSites === true
104
113
  });
105
114
  });
106
115
  }, _SpoHubSiteGetCommand_initOptions = function _SpoHubSiteGetCommand_initOptions() {
107
- this.options.unshift({ option: '-i, --id [id]' }, { option: '-t, --title [title]' }, { option: '-u, --url [url]' }, { option: '--includeAssociatedSites' });
116
+ this.options.unshift({ option: '-i, --id [id]' }, { option: '-t, --title [title]' }, { option: '-u, --url [url]' }, { option: '--includeAssociatedSites' }, { option: '--withAssociatedSites' });
108
117
  }, _SpoHubSiteGetCommand_initValidators = function _SpoHubSiteGetCommand_initValidators() {
109
118
  this.validators.push(async (args) => {
110
119
  if (args.options.id && !validation.isValidGuid(args.options.id)) {
@@ -29,10 +29,14 @@ class SpoHubSiteListCommand extends SpoCommand {
29
29
  }
30
30
  async commandAction(logger, args) {
31
31
  try {
32
+ if (args.options.includeAssociatedSites) {
33
+ await this.warn(logger, `Parameter 'includeAssociatedSites' is deprecated. Please use 'withAssociatedSites' instead`);
34
+ }
32
35
  const spoAdminUrl = await spo.getSpoAdminUrl(logger, this.debug);
33
36
  const hubSitesResult = await odata.getAllItems(`${spoAdminUrl}/_api/hubsites`);
34
37
  const hubSites = hubSitesResult;
35
- if (!(args.options.includeAssociatedSites !== true || args.options.output && args.options.output !== 'json')) {
38
+ const shouldIncludeAssociatedSites = args.options.includeAssociatedSites || args.options.withAssociatedSites;
39
+ if (!(shouldIncludeAssociatedSites !== true || args.options.output && args.options.output !== 'json')) {
36
40
  if (this.debug) {
37
41
  await logger.logToStderr('Retrieving associated sites...');
38
42
  await logger.logToStderr('');
@@ -104,12 +108,15 @@ class SpoHubSiteListCommand extends SpoCommand {
104
108
  _SpoHubSiteListCommand_instances = new WeakSet(), _SpoHubSiteListCommand_initTelemetry = function _SpoHubSiteListCommand_initTelemetry() {
105
109
  this.telemetry.push((args) => {
106
110
  Object.assign(this.telemetryProperties, {
107
- includeAssociatedSites: args.options.includeAssociatedSites === true
111
+ includeAssociatedSites: args.options.includeAssociatedSites === true,
112
+ withAssociatedSites: args.options.withAssociatedSites === true
108
113
  });
109
114
  });
110
115
  }, _SpoHubSiteListCommand_initOptions = function _SpoHubSiteListCommand_initOptions() {
111
116
  this.options.unshift({
112
117
  option: '-i, --includeAssociatedSites'
118
+ }, {
119
+ option: '--withAssociatedSites'
113
120
  });
114
121
  };
115
122
  export default new SpoHubSiteListCommand();
@@ -10,7 +10,6 @@ import request from '../../../../request.js';
10
10
  import { formatting } from '../../../../utils/formatting.js';
11
11
  import { odata } from '../../../../utils/odata.js';
12
12
  import { spo } from '../../../../utils/spo.js';
13
- import { urlUtil } from '../../../../utils/urlUtil.js';
14
13
  import { validation } from '../../../../utils/validation.js';
15
14
  import SpoCommand from '../../../base/SpoCommand.js';
16
15
  import commands from '../../commands.js';
@@ -41,7 +40,9 @@ class SpoListItemBatchSetCommand extends SpoCommand {
41
40
  if (!jsonContent[0].hasOwnProperty(idColumn)) {
42
41
  throw `The specified value for idColumn does not exist in the array. Specified idColumn is '${args.options.idColumn || 'ID'}'. Please specify the correct value.`;
43
42
  }
44
- const listId = await this.getListId(args.options, logger);
43
+ const listId = args.options.listId ?
44
+ args.options.listId :
45
+ await spo.getListId(args.options.webUrl, args.options.listTitle, args.options.listUrl, logger, this.verbose);
45
46
  const fields = await this.getListFields(args.options, listId, jsonContent, idColumn, logger);
46
47
  const userFields = fields.filter(field => field.TypeAsString === 'UserMulti' || field.TypeAsString === 'User');
47
48
  const resolvedUsers = await this.getUsersFromCsv(args.options.webUrl, jsonContent, userFields);
@@ -151,31 +152,6 @@ class SpoListItemBatchSetCommand extends SpoCommand {
151
152
  }
152
153
  return fields;
153
154
  }
154
- async getListId(options, logger) {
155
- if (options.listId) {
156
- return options.listId;
157
- }
158
- if (this.verbose) {
159
- await logger.logToStderr('Retrieving list id');
160
- }
161
- let listUrl = `${options.webUrl}/_api/web`;
162
- if (options.listTitle) {
163
- listUrl += `/lists/getByTitle('${formatting.encodeQueryParameter(options.listTitle)}')`;
164
- }
165
- else {
166
- const listServerRelativeUrl = urlUtil.getServerRelativePath(options.webUrl, options.listUrl);
167
- listUrl += `/GetList('${formatting.encodeQueryParameter(listServerRelativeUrl)}')`;
168
- }
169
- const requestOptions = {
170
- url: `${listUrl}?$select=Id`,
171
- headers: {
172
- 'accept': 'application/json;odata=nometadata'
173
- },
174
- responseType: 'json'
175
- };
176
- const listResult = await request.get(requestOptions);
177
- return listResult.Id;
178
- }
179
155
  async getUsersFromCsv(webUrl, jsonContent, userFields) {
180
156
  if (userFields.length === 0) {
181
157
  return [];
@@ -25,7 +25,7 @@ export class Page {
25
25
  }
26
26
  return ClientSidePage.fromHtml(res.ListItemAllFields.CanvasContent1);
27
27
  }
28
- static async checkout(name, webUrl, logger, debug, verbose) {
28
+ static async checkout(name, webUrl, logger, verbose) {
29
29
  if (verbose) {
30
30
  await logger.log(`Checking out ${name} page...`);
31
31
  }
@@ -77,6 +77,21 @@ export class Page {
77
77
  columns: section.columns.map(column => this.getColumnsInformation(column, isJSONOutput))
78
78
  };
79
79
  }
80
+ /**
81
+ * Publish a modern page in SharePoint Online
82
+ * @param webUrl Absolute URL of the SharePoint site where the page is located
83
+ * @param pageName List relative url of the page to publish
84
+ */
85
+ static async publishPage(webUrl, pageName) {
86
+ const filePath = `${urlUtil.getServerRelativeSiteUrl(webUrl)}/SitePages/${pageName}`;
87
+ const requestOptions = {
88
+ url: `${webUrl}/_api/web/GetFileByServerRelativePath(DecodedUrl='${formatting.encodeQueryParameter(filePath)}')/Publish()`,
89
+ headers: {
90
+ accept: 'application/json;odata=nometadata'
91
+ }
92
+ };
93
+ await request.post(requestOptions);
94
+ }
80
95
  static getPageNameWithExtension(name) {
81
96
  let pageName = name;
82
97
  if (pageName.indexOf('.aspx') < 0) {
@@ -309,6 +309,12 @@ export class ClientSidePage {
309
309
  control.fromHtml(markup);
310
310
  page.pageSettings = control;
311
311
  break;
312
+ case 1:
313
+ // empty canvas column
314
+ control = new CanvasColumn(null, 0);
315
+ control.fromHtml(markup);
316
+ page.mergeColumnToTree(control);
317
+ break;
312
318
  case 3:
313
319
  // client side webpart
314
320
  control = new ClientSideWebpart("");
@@ -380,9 +386,9 @@ export class ClientSidePage {
380
386
  }
381
387
  }
382
388
  }
383
- const sections = this.sections.filter(s => s.order === zoneIndex);
389
+ const sections = this.sections.filter(s => s.order === zoneIndex && s.layoutIndex === (control.controlData?.position.layoutIndex ?? 1));
384
390
  if (sections.length < 1) {
385
- section = new CanvasSection(this, zoneIndex, [], control?.controlData?.position.zoneId, control.controlData?.zoneGroupMetadata);
391
+ section = new CanvasSection(this, zoneIndex, [], control?.controlData);
386
392
  this.sections.push(section);
387
393
  }
388
394
  else {
@@ -406,11 +412,11 @@ export class ClientSidePage {
406
412
  * @param position The position data for the column
407
413
  */
408
414
  mergeColumnToTree(column) {
409
- const order = column.controlData && hOP(column.controlData, "position") && hOP(column.controlData.position, "zoneIndex") ? column.controlData.position.zoneIndex : 0;
415
+ const order = column?.controlData?.position.zoneIndex || 0;
410
416
  let section = null;
411
- const sections = this.sections.filter(s => s.order === order);
417
+ const sections = this.sections.filter(s => s.order === order && s.layoutIndex === (column?.controlData?.position.layoutIndex ?? 1));
412
418
  if (sections.length < 1) {
413
- section = new CanvasSection(this, order, [], column.controlData?.position?.zoneId, column.controlData?.zoneGroupMetadata);
419
+ section = new CanvasSection(this, order, [], column.controlData);
414
420
  this.sections.push(section);
415
421
  }
416
422
  else {
@@ -421,12 +427,16 @@ export class ClientSidePage {
421
427
  }
422
428
  }
423
429
  export class CanvasSection {
424
- constructor(page, order, columns = [], zoneId, zoneGroupMetadata) {
430
+ constructor(page, order, columns = [], controlData) {
425
431
  this.page = page;
426
432
  this.order = order;
427
433
  this.columns = columns;
428
- this.zoneId = zoneId;
429
- this.zoneGroupMetadata = zoneGroupMetadata;
434
+ this.controlData = controlData;
435
+ this.zoneId = this.controlData?.position.zoneId || getGUID();
436
+ this.zoneGroupMetadata = this.controlData?.zoneGroupMetadata;
437
+ this.emphasis = this.controlData?.emphasis;
438
+ this.layoutIndex = this.controlData?.position.layoutIndex ?? 1;
439
+ this.isLayoutReflowOnTop = this.controlData?.position.isLayoutReflowOnTop;
430
440
  }
431
441
  /**
432
442
  * Default column (this.columns[0]) for this section
@@ -454,7 +464,7 @@ export class CanvasSection {
454
464
  }
455
465
  }
456
466
  class CanvasControl {
457
- constructor(controlType, dataVersion, column = undefined, order = 1, id = getGUID(), controlData = null, dynamicDataPaths = null, dynamicDataValues = null) {
467
+ constructor(controlType, dataVersion, column, order = 1, id = getGUID(), controlData, dynamicDataPaths = null, dynamicDataValues = null) {
458
468
  this.controlType = controlType;
459
469
  this.dataVersion = dataVersion;
460
470
  this.column = column;
@@ -542,16 +552,26 @@ export class CanvasColumn extends CanvasControl {
542
552
  }
543
553
  }
544
554
  getControlData() {
545
- return {
546
- displayMode: 2,
555
+ const controlData = {
547
556
  position: {
548
557
  sectionFactor: this.factor,
549
558
  sectionIndex: this.order,
550
- zoneIndex: this.section ? this.section.order : 0,
551
- zoneId: this.section?.zoneId
559
+ zoneIndex: this.section?.order || 0,
560
+ zoneId: this.section?.zoneId,
561
+ layoutIndex: this.section?.layoutIndex,
552
562
  },
553
563
  zoneGroupMetadata: this.section?.zoneGroupMetadata,
564
+ emphasis: this.section?.emphasis
554
565
  };
566
+ if (this.column?.section?.isLayoutReflowOnTop !== undefined) {
567
+ controlData.position.isLayoutReflowOnTop = this.column.section.isLayoutReflowOnTop;
568
+ }
569
+ const isEmptyColumn = this.controls.length === 0;
570
+ if (isEmptyColumn) {
571
+ controlData.id = "emptySection";
572
+ controlData.controlType = 1;
573
+ }
574
+ return controlData;
555
575
  }
556
576
  /**
557
577
  * Removes this column and all contained controls from the collection
@@ -650,7 +670,7 @@ export class ClientSideText extends ClientSidePart {
650
670
  this._text = text;
651
671
  }
652
672
  getControlData() {
653
- return {
673
+ const controlData = {
654
674
  controlType: this.controlType,
655
675
  editorType: "CKEditor",
656
676
  id: this.id,
@@ -659,10 +679,16 @@ export class ClientSideText extends ClientSidePart {
659
679
  sectionFactor: this.column ? this.column.factor : 0,
660
680
  sectionIndex: this.column ? this.column.order : 0,
661
681
  zoneIndex: this.column && this.column.section ? this.column.section.order : 0,
662
- zoneId: this.column?.section?.zoneId
682
+ zoneId: this.column?.section?.zoneId,
683
+ layoutIndex: this.column?.section?.layoutIndex
663
684
  },
664
685
  zoneGroupMetadata: this.column?.section?.zoneGroupMetadata,
686
+ emphasis: this.column?.section?.emphasis,
665
687
  };
688
+ if (this.column?.section?.isLayoutReflowOnTop !== undefined) {
689
+ controlData.position.isLayoutReflowOnTop = this.column.section.isLayoutReflowOnTop;
690
+ }
691
+ return controlData;
666
692
  }
667
693
  toHtml(index) {
668
694
  // set our order to the value passed in
@@ -767,7 +793,7 @@ export class ClientSideWebpart extends ClientSidePart {
767
793
  this.htmlProperties = htmlProps.length > 0 ? htmlProps[0] : "";
768
794
  }
769
795
  getControlData() {
770
- return {
796
+ const controlData = {
771
797
  controlType: this.controlType,
772
798
  id: this.id,
773
799
  position: {
@@ -775,11 +801,17 @@ export class ClientSideWebpart extends ClientSidePart {
775
801
  sectionFactor: this.column ? this.column.factor : 0,
776
802
  sectionIndex: this.column ? this.column.order : 0,
777
803
  zoneIndex: this.column && this.column.section ? this.column.section.order : 0,
778
- zoneId: this.column?.section?.zoneId
804
+ zoneId: this.column?.section?.zoneId,
805
+ layoutIndex: this.column?.section?.layoutIndex,
779
806
  },
780
807
  webPartId: this.webPartId,
781
808
  zoneGroupMetadata: this.column?.section?.zoneGroupMetadata,
809
+ emphasis: this.column?.section?.emphasis,
782
810
  };
811
+ if (this.column?.section?.isLayoutReflowOnTop !== undefined) {
812
+ controlData.position.isLayoutReflowOnTop = this.column.section.isLayoutReflowOnTop;
813
+ }
814
+ return controlData;
783
815
  }
784
816
  renderHtmlProperties() {
785
817
  const html = [];
@@ -63,7 +63,7 @@ class SpoPageAddCommand extends SpoCommand {
63
63
  itemId = template.UniqueId;
64
64
  const file = await spo.getFileAsListItemByUrl(args.options.webUrl, serverRelativeFileUrl, logger, this.verbose);
65
65
  const listItemId = file.Id;
66
- const pageProps = await Page.checkout(pageName, args.options.webUrl, logger, this.debug, this.verbose);
66
+ const pageProps = await Page.checkout(pageName, args.options.webUrl, logger, this.verbose);
67
67
  if (pageProps) {
68
68
  pageId = pageProps.Id;
69
69
  bannerImageUrl = pageProps.BannerImageUrl;
@@ -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 { StandardWebPartUtils } from '../../StandardWebPartTypes.js';
14
+ import { Page } from './Page.js';
14
15
  class SpoPageClientSideWebPartAddCommand extends SpoCommand {
15
16
  get name() {
16
17
  return commands.PAGE_CLIENTSIDEWEBPART_ADD;
@@ -52,14 +53,7 @@ class SpoPageClientSideWebPartAddCommand extends SpoCommand {
52
53
  };
53
54
  let page = await request.get(requestOptions);
54
55
  if (!page.IsPageCheckedOutToCurrentUser) {
55
- const requestOptions = {
56
- url: `${args.options.webUrl}/_api/sitepages/pages/GetByUrl('sitepages/${formatting.encodeQueryParameter(pageFullName)}')/checkoutpage`,
57
- headers: {
58
- 'accept': 'application/json;odata=nometadata'
59
- },
60
- responseType: 'json'
61
- };
62
- page = await request.post(requestOptions);
56
+ page = await Page.checkout(pageFullName, args.options.webUrl, logger, this.verbose);
63
57
  }
64
58
  if (page) {
65
59
  layoutWebpartsContent = page.LayoutWebpartsContent;