@pnp/cli-microsoft365 10.3.0-beta.f5e6f85 → 10.4.0-beta.17b3a55

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 (36) hide show
  1. package/allCommands.json +1 -1
  2. package/allCommandsFull.json +1 -1
  3. package/dist/config.js +3 -1
  4. package/dist/m365/entra/commands/app/app-add.js +3 -0
  5. package/dist/m365/entra/commands/resourcenamespace/resourcenamespace-list.js +28 -0
  6. package/dist/m365/entra/commands/rolepermission/rolepermission-list.js +42 -0
  7. package/dist/m365/entra/commands.js +2 -0
  8. package/dist/m365/outlook/commands/mailbox/mailbox-settings-get.js +71 -0
  9. package/dist/m365/outlook/commands/mailbox/mailbox-settings-set.js +5 -2
  10. package/dist/m365/outlook/commands.js +1 -0
  11. package/dist/m365/spe/commands/container/container-activate.js +50 -0
  12. package/dist/m365/spe/commands.js +1 -0
  13. package/dist/m365/spo/commands/list/list-defaultvalue-clear.js +184 -0
  14. package/dist/m365/spo/commands/list/list-defaultvalue-remove.js +181 -0
  15. package/dist/m365/spo/commands/list/list-defaultvalue-set.js +210 -0
  16. package/dist/m365/spo/commands/mail/mail-send.js +2 -0
  17. package/dist/m365/spo/commands/page/page-get.js +40 -27
  18. package/dist/m365/spo/commands.js +3 -0
  19. package/dist/m365/tenant/commands/report/report-settings-get.js +32 -0
  20. package/dist/m365/tenant/commands/report/report-settings-set.js +47 -0
  21. package/dist/m365/tenant/commands.js +2 -0
  22. package/docs/docs/cmd/entra/app/app-add.mdx +1 -1
  23. package/docs/docs/cmd/entra/resourcenamespace/resourcenamespace-list.mdx +96 -0
  24. package/docs/docs/cmd/entra/roledefinition/roledefinition-add.mdx +4 -0
  25. package/docs/docs/cmd/entra/roledefinition/roledefinition-set.mdx +4 -0
  26. package/docs/docs/cmd/entra/rolepermission/rolepermission-list.mdx +164 -0
  27. package/docs/docs/cmd/outlook/mailbox/mailbox-settings-get.mdx +131 -0
  28. package/docs/docs/cmd/spe/container/container-activate.mdx +34 -0
  29. package/docs/docs/cmd/spo/list/list-defaultvalue-clear.mdx +62 -0
  30. package/docs/docs/cmd/spo/list/list-defaultvalue-remove.mdx +62 -0
  31. package/docs/docs/cmd/spo/list/list-defaultvalue-set.mdx +112 -0
  32. package/docs/docs/cmd/spo/page/page-get.mdx +11 -2
  33. package/docs/docs/cmd/tenant/report/report-settings-get.mdx +67 -0
  34. package/docs/docs/cmd/tenant/report/report-settings-set.mdx +32 -0
  35. package/npm-shrinkwrap.json +2 -2
  36. package/package.json +1 -1
package/dist/config.js CHANGED
@@ -34,9 +34,11 @@ export default {
34
34
  'https://graph.microsoft.com/Place.Read.All',
35
35
  'https://graph.microsoft.com/Policy.Read.All',
36
36
  'https://graph.microsoft.com/RecordsManagement.ReadWrite.All',
37
- 'https://graph.microsoft.com/Reports.Read.All',
37
+ 'https://graph.microsoft.com/Reports.ReadWrite.All',
38
+ 'https://graph.microsoft.com/ReportSettings.ReadWrite.All',
38
39
  'https://graph.microsoft.com/RoleAssignmentSchedule.ReadWrite.Directory',
39
40
  'https://graph.microsoft.com/RoleEligibilitySchedule.Read.Directory',
41
+ 'https://graph.microsoft.com/RoleManagement.Read.Directory',
40
42
  'https://graph.microsoft.com/SecurityEvents.Read.All',
41
43
  'https://graph.microsoft.com/ServiceHealth.Read.All',
42
44
  'https://graph.microsoft.com/ServiceMessage.Read.All',
@@ -476,6 +476,9 @@ _a = EntraAppAddCommand, _EntraAppAddCommand_instances = new WeakSet(), _EntraAp
476
476
  if (args.options.redirectUris && !args.options.platform) {
477
477
  return `When you specify redirectUris you also need to specify platform`;
478
478
  }
479
+ if (args.options.platform && ['spa', 'web', 'publicClient'].indexOf(args.options.platform) > -1 && !args.options.redirectUris) {
480
+ return `When you use platform spa, web or publicClient, you'll need to specify redirectUris`;
481
+ }
479
482
  if (args.options.certificateFile && args.options.certificateBase64Encoded) {
480
483
  return 'Specify either certificateFile or certificateBase64Encoded but not both';
481
484
  }
@@ -0,0 +1,28 @@
1
+ import { odata } from '../../../../utils/odata.js';
2
+ import GraphCommand from '../../../base/GraphCommand.js';
3
+ import commands from '../../commands.js';
4
+ class EntraResourcenamespaceListCommand extends GraphCommand {
5
+ get name() {
6
+ return commands.RESOURCENAMESPACE_LIST;
7
+ }
8
+ get description() {
9
+ return 'Get a list of the RBAC resource namespaces and their properties';
10
+ }
11
+ defaultProperties() {
12
+ return ['id', 'name'];
13
+ }
14
+ async commandAction(logger) {
15
+ if (this.verbose) {
16
+ await logger.logToStderr('Getting a list of the RBAC resource namespaces and their properties...');
17
+ }
18
+ try {
19
+ const results = await odata.getAllItems(`${this.resource}/beta/roleManagement/directory/resourceNamespaces`);
20
+ await logger.log(results);
21
+ }
22
+ catch (err) {
23
+ this.handleRejectedODataJsonPromise(err);
24
+ }
25
+ }
26
+ }
27
+ export default new EntraResourcenamespaceListCommand();
28
+ //# sourceMappingURL=resourcenamespace-list.js.map
@@ -0,0 +1,42 @@
1
+ import { odata } from '../../../../utils/odata.js';
2
+ import GraphCommand from '../../../base/GraphCommand.js';
3
+ import commands from '../../commands.js';
4
+ import { z } from 'zod';
5
+ import { globalOptionsZod } from '../../../../Command.js';
6
+ import { zod } from '../../../../utils/zod.js';
7
+ const options = globalOptionsZod
8
+ .extend({
9
+ resourceNamespace: zod.alias('n', z.string()),
10
+ privileged: zod.alias('p', z.boolean().optional())
11
+ })
12
+ .strict();
13
+ class EntraRolePermissionListCommand extends GraphCommand {
14
+ get name() {
15
+ return commands.ROLEPERMISSION_LIST;
16
+ }
17
+ get description() {
18
+ return 'Lists all Microsoft Entra ID role permissions';
19
+ }
20
+ defaultProperties() {
21
+ return ['id', 'name', 'actionVerb', 'isPrivileged'];
22
+ }
23
+ get schema() {
24
+ return options;
25
+ }
26
+ async commandAction(logger, args) {
27
+ if (this.verbose) {
28
+ await logger.logToStderr('Getting Microsoft Entra ID role permissions...');
29
+ }
30
+ try {
31
+ const queryString = args.options.privileged ? '?$filter=isPrivileged eq true' : '';
32
+ const url = `${this.resource}/beta/roleManagement/directory/resourceNamespaces/${args.options.resourceNamespace}/resourceActions${queryString}`;
33
+ const results = await odata.getAllItems(url);
34
+ await logger.log(results);
35
+ }
36
+ catch (err) {
37
+ this.handleRejectedODataJsonPromise(err);
38
+ }
39
+ }
40
+ }
41
+ export default new EntraRolePermissionListCommand();
42
+ //# sourceMappingURL=rolepermission-list.js.map
@@ -88,11 +88,13 @@ export default {
88
88
  PIM_ROLE_ASSIGNMENT_ELIGIBILITY_LIST: `${prefix} pim role assignment eligibility list`,
89
89
  PIM_ROLE_REQUEST_LIST: `${prefix} pim role request list`,
90
90
  POLICY_LIST: `${prefix} policy list`,
91
+ RESOURCENAMESPACE_LIST: `${prefix} resourcenamespace list`,
91
92
  ROLEDEFINITION_ADD: `${prefix} roledefinition add`,
92
93
  ROLEDEFINITION_LIST: `${prefix} roledefinition list`,
93
94
  ROLEDEFINITION_GET: `${prefix} roledefinition get`,
94
95
  ROLEDEFINITION_REMOVE: `${prefix} roledefinition remove`,
95
96
  ROLEDEFINITION_SET: `${prefix} roledefinition set`,
97
+ ROLEPERMISSION_LIST: `${prefix} rolepermission list`,
96
98
  SITECLASSIFICATION_DISABLE: `${prefix} siteclassification disable`,
97
99
  SITECLASSIFICATION_ENABLE: `${prefix} siteclassification enable`,
98
100
  SITECLASSIFICATION_GET: `${prefix} siteclassification get`,
@@ -0,0 +1,71 @@
1
+ import { z } from 'zod';
2
+ import { globalOptionsZod } from '../../../../Command.js';
3
+ import { zod } from '../../../../utils/zod.js';
4
+ import GraphCommand from '../../../base/GraphCommand.js';
5
+ import commands from '../../commands.js';
6
+ import { validation } from '../../../../utils/validation.js';
7
+ import request from '../../../../request.js';
8
+ import { accessToken } from '../../../../utils/accessToken.js';
9
+ import auth from '../../../../Auth.js';
10
+ const options = globalOptionsZod
11
+ .extend({
12
+ userId: zod.alias('i', z.string().refine(id => validation.isValidGuid(id), id => ({
13
+ message: `'${id}' is not a valid GUID.`
14
+ })).optional()),
15
+ userName: zod.alias('n', z.string().refine(name => validation.isValidUserPrincipalName(name), name => ({
16
+ message: `'${name}' is not a valid UPN.`
17
+ })).optional())
18
+ })
19
+ .strict();
20
+ class OutlookMailboxSettingsGetCommand extends GraphCommand {
21
+ get name() {
22
+ return commands.MAILBOX_SETTINGS_GET;
23
+ }
24
+ get description() {
25
+ return `Get the user's mailbox settings`;
26
+ }
27
+ get schema() {
28
+ return options;
29
+ }
30
+ getRefinedSchema(schema) {
31
+ return schema
32
+ .refine(options => !(options.userId && options.userName), {
33
+ message: 'Specify either userId or userName, but not both'
34
+ });
35
+ }
36
+ async commandAction(logger, args) {
37
+ const isAppOnlyAccessToken = accessToken.isAppOnlyAccessToken(auth.connection.accessTokens[auth.defaultResource].accessToken);
38
+ let requestUrl = `${this.resource}/v1.0/me/mailboxSettings`;
39
+ if (isAppOnlyAccessToken) {
40
+ if (!args.options.userId && !args.options.userName) {
41
+ throw 'When running with application permissions either userId or userName is required';
42
+ }
43
+ const userIdentifier = args.options.userId ?? args.options.userName;
44
+ if (this.verbose) {
45
+ await logger.logToStderr(`Retrieving mailbox settings for user ${userIdentifier}...`);
46
+ }
47
+ requestUrl = `${this.resource}/v1.0/users('${userIdentifier}')/mailboxSettings`;
48
+ }
49
+ else {
50
+ if (args.options.userId || args.options.userName) {
51
+ throw 'You can retrieve mailbox settings of other users only if CLI is authenticated in app-only mode';
52
+ }
53
+ }
54
+ const requestOptions = {
55
+ url: requestUrl,
56
+ headers: {
57
+ accept: 'application/json;odata.metadata=none'
58
+ },
59
+ responseType: 'json'
60
+ };
61
+ try {
62
+ const result = await request.get(requestOptions);
63
+ await logger.log(result);
64
+ }
65
+ catch (err) {
66
+ this.handleRejectedODataJsonPromise(err);
67
+ }
68
+ }
69
+ }
70
+ export default new OutlookMailboxSettingsGetCommand();
71
+ //# sourceMappingURL=mailbox-settings-get.js.map
@@ -46,6 +46,9 @@ class OutlookMailboxSettingsSetCommand extends GraphCommand {
46
46
  }
47
47
  getRefinedSchema(schema) {
48
48
  return schema
49
+ .refine(options => !(options.userId && options.userName), {
50
+ message: 'Specify either userId or userName, but not both'
51
+ })
49
52
  .refine(options => [options.workingDays, options.workingHoursStartTime, options.workingHoursEndTime, options.workingHoursTimeZone,
50
53
  options.autoReplyStatus, options.autoReplyExternalAudience, options.autoReplyExternalMessage, options.autoReplyInternalMessage,
51
54
  options.autoReplyStartDateTime, options.autoReplyStartTimeZone, options.autoReplyEndDateTime, options.autoReplyEndTimeZone,
@@ -57,8 +60,8 @@ class OutlookMailboxSettingsSetCommand extends GraphCommand {
57
60
  const isAppOnlyAccessToken = accessToken.isAppOnlyAccessToken(auth.connection.accessTokens[auth.defaultResource].accessToken);
58
61
  let requestUrl = `${this.resource}/v1.0/me/mailboxSettings`;
59
62
  if (isAppOnlyAccessToken) {
60
- if (args.options.userId && args.options.userName) {
61
- throw 'When running with application permissions either userId or userName is required, but not both';
63
+ if (!args.options.userId && !args.options.userName) {
64
+ throw 'When running with application permissions either userId or userName is required';
62
65
  }
63
66
  const userIdentifier = args.options.userId ?? args.options.userName;
64
67
  if (this.verbose) {
@@ -1,6 +1,7 @@
1
1
  const prefix = 'outlook';
2
2
  export default {
3
3
  MAIL_SEND: `${prefix} mail send`,
4
+ MAILBOX_SETTINGS_GET: `${prefix} mailbox settings get`,
4
5
  MAILBOX_SETTINGS_SET: `${prefix} mailbox settings set`,
5
6
  MESSAGE_GET: `${prefix} message get`,
6
7
  MESSAGE_LIST: `${prefix} message list`,
@@ -0,0 +1,50 @@
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 _SpeContainerActivateCommand_instances, _SpeContainerActivateCommand_initOptions, _SpeContainerActivateCommand_initTypes;
7
+ import GraphCommand from '../../../base/GraphCommand.js';
8
+ import commands from '../../commands.js';
9
+ import request from '../../../../request.js';
10
+ import { formatting } from '../../../../utils/formatting.js';
11
+ class SpeContainerActivateCommand extends GraphCommand {
12
+ get name() {
13
+ return commands.CONTAINER_ACTIVATE;
14
+ }
15
+ get description() {
16
+ return 'Activates a container';
17
+ }
18
+ constructor() {
19
+ super();
20
+ _SpeContainerActivateCommand_instances.add(this);
21
+ __classPrivateFieldGet(this, _SpeContainerActivateCommand_instances, "m", _SpeContainerActivateCommand_initOptions).call(this);
22
+ __classPrivateFieldGet(this, _SpeContainerActivateCommand_instances, "m", _SpeContainerActivateCommand_initTypes).call(this);
23
+ }
24
+ async commandAction(logger, args) {
25
+ if (this.verbose) {
26
+ await logger.logToStderr(`Activating a container with id '${args.options.id}'...`);
27
+ }
28
+ try {
29
+ const requestOptions = {
30
+ url: `${this.resource}/v1.0/storage/fileStorage/containers/${formatting.encodeQueryParameter(args.options.id)}/activate`,
31
+ headers: {
32
+ 'content-type': 'application/json;odata=nometadata',
33
+ 'accept': 'application/json;odata.metadata=none'
34
+ },
35
+ responseType: 'json'
36
+ };
37
+ await request.post(requestOptions);
38
+ }
39
+ catch (err) {
40
+ this.handleRejectedODataJsonPromise(err);
41
+ }
42
+ }
43
+ }
44
+ _SpeContainerActivateCommand_instances = new WeakSet(), _SpeContainerActivateCommand_initOptions = function _SpeContainerActivateCommand_initOptions() {
45
+ this.options.unshift({ option: '-i, --id <id>' });
46
+ }, _SpeContainerActivateCommand_initTypes = function _SpeContainerActivateCommand_initTypes() {
47
+ this.types.string.push('id');
48
+ };
49
+ export default new SpeContainerActivateCommand();
50
+ //# sourceMappingURL=container-activate.js.map
@@ -1,5 +1,6 @@
1
1
  const prefix = 'spe';
2
2
  export default {
3
+ CONTAINER_ACTIVATE: `${prefix} container activate`,
3
4
  CONTAINER_GET: `${prefix} container get`,
4
5
  CONTAINER_LIST: `${prefix} container list`,
5
6
  CONTAINERTYPE_ADD: `${prefix} containertype add`,
@@ -0,0 +1,184 @@
1
+ import SpoCommand from '../../../base/SpoCommand.js';
2
+ import { globalOptionsZod } from '../../../../Command.js';
3
+ import { z } from 'zod';
4
+ import { zod } from '../../../../utils/zod.js';
5
+ import commands from '../../commands.js';
6
+ import { DOMParser } from '@xmldom/xmldom';
7
+ import { validation } from '../../../../utils/validation.js';
8
+ import { urlUtil } from '../../../../utils/urlUtil.js';
9
+ import request from '../../../../request.js';
10
+ import { formatting } from '../../../../utils/formatting.js';
11
+ import { cli } from '../../../../cli/cli.js';
12
+ const options = globalOptionsZod
13
+ .extend({
14
+ webUrl: zod.alias('u', z.string()
15
+ .refine(url => validation.isValidSharePointUrl(url) === true, url => ({
16
+ message: `'${url}' is not a valid SharePoint Online site URL.`
17
+ }))),
18
+ listId: zod.alias('i', z.string().optional()
19
+ .refine(id => id === undefined || validation.isValidGuid(id), id => ({
20
+ message: `'${id}' is not a valid GUID.`
21
+ }))),
22
+ listTitle: zod.alias('t', z.string().optional()),
23
+ listUrl: z.string().optional(),
24
+ fieldName: z.string().optional(),
25
+ folderUrl: z.string().optional(),
26
+ force: zod.alias('f', z.boolean().optional())
27
+ })
28
+ .strict();
29
+ class SpoListDefaultValueClearCommand extends SpoCommand {
30
+ get name() {
31
+ return commands.LIST_DEFAULTVALUE_CLEAR;
32
+ }
33
+ get description() {
34
+ return 'Clears default column values for a specific document library';
35
+ }
36
+ get schema() {
37
+ return options;
38
+ }
39
+ getRefinedSchema(schema) {
40
+ return schema
41
+ .refine(options => [options.listId, options.listTitle, options.listUrl].filter(o => o !== undefined).length === 1, {
42
+ message: 'Use one of the following options: listId, listTitle, listUrl.'
43
+ })
44
+ .refine(options => (options.fieldName !== undefined) !== (options.folderUrl !== undefined) || (options.fieldName === undefined && options.folderUrl === undefined), {
45
+ message: `Specify 'fieldName' or 'folderUrl', but not both.`
46
+ });
47
+ }
48
+ async commandAction(logger, args) {
49
+ if (!args.options.force) {
50
+ const result = await cli.promptForConfirmation({ message: `Are you sure you want to clear all default values${args.options.fieldName ? ` for field '${args.options.fieldName}'` : args.options.folderUrl ? ` for folder ${args.options.folderUrl}` : ''}?` });
51
+ if (!result) {
52
+ return;
53
+ }
54
+ }
55
+ try {
56
+ if (this.verbose) {
57
+ await logger.logToStderr(`Clearing all default column values${args.options.fieldName ? ` for field ${args.options.fieldName}` : args.options.folderUrl ? `for folder '${args.options.folderUrl}'` : ''}...`);
58
+ await logger.logToStderr(`Getting server-relative URL of the list...`);
59
+ }
60
+ const listServerRelUrl = await this.getServerRelativeListUrl(args.options);
61
+ if (this.verbose) {
62
+ await logger.logToStderr(`List server-relative URL: ${listServerRelUrl}`);
63
+ await logger.logToStderr(`Getting default column values...`);
64
+ }
65
+ const defaultValuesXml = await this.getDefaultColumnValuesXml(args.options.webUrl, listServerRelUrl);
66
+ if (defaultValuesXml === null) {
67
+ if (this.verbose) {
68
+ await logger.logToStderr(`No default column values found.`);
69
+ }
70
+ return;
71
+ }
72
+ const trimmedXml = this.removeFieldsFromXml(defaultValuesXml, args.options);
73
+ await this.uploadDefaultColumnValuesXml(args.options.webUrl, listServerRelUrl, trimmedXml);
74
+ }
75
+ catch (err) {
76
+ this.handleRejectedODataJsonPromise(err);
77
+ }
78
+ }
79
+ async getServerRelativeListUrl(options) {
80
+ const requestOptions = {
81
+ url: `${options.webUrl}/_api/Web`,
82
+ headers: {
83
+ accept: 'application/json;odata=nometadata'
84
+ },
85
+ responseType: 'json'
86
+ };
87
+ if (options.listUrl) {
88
+ const serverRelativeUrl = urlUtil.getServerRelativePath(options.webUrl, options.listUrl);
89
+ requestOptions.url += `/GetList('${formatting.encodeQueryParameter(serverRelativeUrl)}')`;
90
+ }
91
+ else if (options.listId) {
92
+ requestOptions.url += `/Lists('${options.listId}')`;
93
+ }
94
+ else if (options.listTitle) {
95
+ requestOptions.url += `/Lists/GetByTitle('${formatting.encodeQueryParameter(options.listTitle)}')`;
96
+ }
97
+ requestOptions.url += '?$expand=RootFolder&$select=RootFolder/ServerRelativeUrl,BaseTemplate';
98
+ try {
99
+ const response = await request.get(requestOptions);
100
+ if (response.BaseTemplate !== 101) {
101
+ throw `The specified list is not a document library.`;
102
+ }
103
+ return response.RootFolder.ServerRelativeUrl;
104
+ }
105
+ catch (error) {
106
+ if (error.status === 404) {
107
+ throw `List '${options.listId || options.listTitle || options.listUrl}' was not found.`;
108
+ }
109
+ throw error;
110
+ }
111
+ }
112
+ async getDefaultColumnValuesXml(webUrl, listServerRelUrl) {
113
+ try {
114
+ const requestOptions = {
115
+ url: `${webUrl}/_api/Web/GetFileByServerRelativePath(decodedUrl='${formatting.encodeQueryParameter(listServerRelUrl + '/Forms/client_LocationBasedDefaults.html')}')/$value`,
116
+ headers: {
117
+ accept: 'application/json;odata=nometadata'
118
+ },
119
+ responseType: 'json'
120
+ };
121
+ const defaultValuesXml = await request.get(requestOptions);
122
+ return defaultValuesXml;
123
+ }
124
+ catch (err) {
125
+ // For lists that have never had default column values set, the client_LocationBasedDefaults.html file does not exist.
126
+ if (err.status === 404) {
127
+ return null;
128
+ }
129
+ throw err;
130
+ }
131
+ }
132
+ removeFieldsFromXml(xml, options) {
133
+ if (!options.fieldName && !options.folderUrl) {
134
+ return '<MetadataDefaults />';
135
+ }
136
+ let folderUrlToRemove = null;
137
+ if (options.folderUrl) {
138
+ folderUrlToRemove = urlUtil.removeTrailingSlashes(urlUtil.getServerRelativePath(options.webUrl, options.folderUrl));
139
+ }
140
+ const parser = new DOMParser();
141
+ const doc = parser.parseFromString(xml, 'application/xml');
142
+ const folderLinks = doc.getElementsByTagName('a');
143
+ for (let i = 0; i < folderLinks.length; i++) {
144
+ const folderNode = folderLinks[i];
145
+ const folderUrl = folderNode.getAttribute('href');
146
+ if (folderUrlToRemove && folderUrlToRemove.toLowerCase() === decodeURIComponent(folderUrl).toLowerCase()) {
147
+ folderNode.parentNode.removeChild(folderNode);
148
+ break;
149
+ }
150
+ else if (options.fieldName) {
151
+ const defaultValues = folderNode.getElementsByTagName('DefaultValue');
152
+ for (let j = 0; j < defaultValues.length; j++) {
153
+ const defaultValueNode = defaultValues[j];
154
+ const fieldName = defaultValueNode.getAttribute('FieldName');
155
+ if (fieldName.toLowerCase() === options.fieldName.toLowerCase()) {
156
+ // Remove the entire folder node if it becomes empty
157
+ if (folderNode.childNodes.length === 1) {
158
+ folderNode.parentNode.removeChild(defaultValueNode.parentNode);
159
+ }
160
+ else {
161
+ folderNode.removeChild(defaultValueNode);
162
+ }
163
+ break;
164
+ }
165
+ }
166
+ }
167
+ }
168
+ return doc.toString();
169
+ }
170
+ async uploadDefaultColumnValuesXml(webUrl, listServerRelUrl, xml) {
171
+ const requestOptions = {
172
+ url: `${webUrl}/_api/Web/GetFileByServerRelativePath(decodedUrl='${formatting.encodeQueryParameter(listServerRelUrl + '/Forms/client_LocationBasedDefaults.html')}')/$value`,
173
+ headers: {
174
+ accept: 'application/json;odata=nometadata',
175
+ 'If-Match': '*'
176
+ },
177
+ responseType: 'json',
178
+ data: xml
179
+ };
180
+ await request.put(requestOptions);
181
+ }
182
+ }
183
+ export default new SpoListDefaultValueClearCommand();
184
+ //# sourceMappingURL=list-defaultvalue-clear.js.map
@@ -0,0 +1,181 @@
1
+ import SpoCommand from '../../../base/SpoCommand.js';
2
+ import { globalOptionsZod } from '../../../../Command.js';
3
+ import { z } from 'zod';
4
+ import { zod } from '../../../../utils/zod.js';
5
+ import commands from '../../commands.js';
6
+ import { DOMParser } from '@xmldom/xmldom';
7
+ import { validation } from '../../../../utils/validation.js';
8
+ import { urlUtil } from '../../../../utils/urlUtil.js';
9
+ import request from '../../../../request.js';
10
+ import { formatting } from '../../../../utils/formatting.js';
11
+ import { cli } from '../../../../cli/cli.js';
12
+ const options = globalOptionsZod
13
+ .extend({
14
+ webUrl: zod.alias('u', z.string()
15
+ .refine(url => validation.isValidSharePointUrl(url) === true, url => ({
16
+ message: `'${url}' is not a valid SharePoint Online site URL.`
17
+ }))),
18
+ listId: zod.alias('i', z.string().optional()
19
+ .refine(id => id === undefined || validation.isValidGuid(id), id => ({
20
+ message: `'${id}' is not a valid GUID.`
21
+ }))),
22
+ listTitle: zod.alias('t', z.string().optional()),
23
+ listUrl: z.string().optional(),
24
+ fieldName: z.string(),
25
+ folderUrl: z.string().optional(),
26
+ force: zod.alias('f', z.boolean().optional())
27
+ })
28
+ .strict();
29
+ class SpoListDefaultValueRemoveCommand extends SpoCommand {
30
+ get name() {
31
+ return commands.LIST_DEFAULTVALUE_REMOVE;
32
+ }
33
+ get description() {
34
+ return 'Removes a specific default column value for a specific document library';
35
+ }
36
+ get schema() {
37
+ return options;
38
+ }
39
+ getRefinedSchema(schema) {
40
+ return schema
41
+ .refine(options => [options.listId, options.listTitle, options.listUrl].filter(o => o !== undefined).length === 1, {
42
+ message: 'Use one of the following options: listId, listTitle, listUrl.'
43
+ });
44
+ }
45
+ async commandAction(logger, args) {
46
+ if (!args.options.force) {
47
+ const result = await cli.promptForConfirmation({ message: `Are you sure you want to remove default column value '${args.options.fieldName}' from ${args.options.folderUrl ? `'${args.options.folderUrl}'` : 'the root of the list'}?` });
48
+ if (!result) {
49
+ return;
50
+ }
51
+ }
52
+ try {
53
+ if (this.verbose) {
54
+ await logger.logToStderr(`Removing default column value '${args.options.fieldName}' from ${args.options.folderUrl ? `'${args.options.folderUrl}'` : 'the root of the list'}.`);
55
+ await logger.logToStderr(`Getting server-relative URL of the list...`);
56
+ }
57
+ const listServerRelUrl = await this.getServerRelativeListUrl(args.options);
58
+ let folderUrl = listServerRelUrl;
59
+ if (args.options.folderUrl) {
60
+ folderUrl = urlUtil.getServerRelativePath(args.options.webUrl, urlUtil.removeTrailingSlashes(args.options.folderUrl));
61
+ }
62
+ if (this.verbose) {
63
+ await logger.logToStderr(`Getting default column values...`);
64
+ }
65
+ const defaultValuesXml = await this.getDefaultColumnValuesXml(args.options.webUrl, listServerRelUrl);
66
+ const removeDefaultValueResult = this.removeFieldFromXml(defaultValuesXml, args.options.fieldName, folderUrl);
67
+ if (!removeDefaultValueResult.isFieldFound) {
68
+ throw `Default column value '${args.options.fieldName}' was not found.`;
69
+ }
70
+ if (this.verbose) {
71
+ await logger.logToStderr(`Uploading default column values to list...`);
72
+ }
73
+ await this.uploadDefaultColumnValuesXml(args.options.webUrl, listServerRelUrl, removeDefaultValueResult.xml);
74
+ }
75
+ catch (err) {
76
+ this.handleRejectedODataJsonPromise(err);
77
+ }
78
+ }
79
+ async getServerRelativeListUrl(options) {
80
+ const requestOptions = {
81
+ url: `${options.webUrl}/_api/Web`,
82
+ headers: {
83
+ accept: 'application/json;odata=nometadata'
84
+ },
85
+ responseType: 'json'
86
+ };
87
+ if (options.listUrl) {
88
+ const serverRelativeUrl = urlUtil.getServerRelativePath(options.webUrl, options.listUrl);
89
+ requestOptions.url += `/GetList('${formatting.encodeQueryParameter(serverRelativeUrl)}')`;
90
+ }
91
+ else if (options.listId) {
92
+ requestOptions.url += `/Lists('${options.listId}')`;
93
+ }
94
+ else if (options.listTitle) {
95
+ requestOptions.url += `/Lists/GetByTitle('${formatting.encodeQueryParameter(options.listTitle)}')`;
96
+ }
97
+ requestOptions.url += '?$expand=RootFolder&$select=RootFolder/ServerRelativeUrl,BaseTemplate';
98
+ try {
99
+ const response = await request.get(requestOptions);
100
+ if (response.BaseTemplate !== 101) {
101
+ throw `The specified list is not a document library.`;
102
+ }
103
+ return response.RootFolder.ServerRelativeUrl;
104
+ }
105
+ catch (error) {
106
+ if (error.status === 404) {
107
+ throw `List '${options.listId || options.listTitle || options.listUrl}' was not found.`;
108
+ }
109
+ throw error;
110
+ }
111
+ }
112
+ async getDefaultColumnValuesXml(webUrl, listServerRelUrl) {
113
+ try {
114
+ const requestOptions = {
115
+ url: `${webUrl}/_api/Web/GetFileByServerRelativePath(decodedUrl='${formatting.encodeQueryParameter(listServerRelUrl + '/Forms/client_LocationBasedDefaults.html')}')/$value`,
116
+ headers: {
117
+ accept: 'application/json;odata=nometadata'
118
+ },
119
+ responseType: 'json'
120
+ };
121
+ const defaultValuesXml = await request.get(requestOptions);
122
+ return defaultValuesXml;
123
+ }
124
+ catch (err) {
125
+ // For lists that have never had default column values set, the client_LocationBasedDefaults.html file does not exist.
126
+ if (err.status === 404) {
127
+ return null;
128
+ }
129
+ throw err;
130
+ }
131
+ }
132
+ removeFieldFromXml(xml, fieldName, folderUrl) {
133
+ if (xml === null) {
134
+ return { isFieldFound: false };
135
+ }
136
+ // Encode all spaces in the folder URL
137
+ const encodedFolderUrl = folderUrl.replace(/ /g, '%20');
138
+ const parser = new DOMParser();
139
+ const doc = parser.parseFromString(xml, 'application/xml');
140
+ const folderLinks = doc.getElementsByTagName('a');
141
+ for (let i = 0; i < folderLinks.length; i++) {
142
+ const folderNode = folderLinks[i];
143
+ const folderNodeUrl = folderNode.getAttribute('href');
144
+ if (encodedFolderUrl.toLowerCase() !== folderNodeUrl.toLowerCase()) {
145
+ continue;
146
+ }
147
+ const defaultValues = folderNode.getElementsByTagName('DefaultValue');
148
+ for (let j = 0; j < defaultValues.length; j++) {
149
+ const defaultValueNode = defaultValues[j];
150
+ const defaultValueNodeField = defaultValueNode.getAttribute('FieldName');
151
+ if (defaultValueNodeField !== fieldName) {
152
+ continue;
153
+ }
154
+ if (folderNode.childNodes.length === 1) {
155
+ // No other default values found in the folder, let's remove the folder node
156
+ folderNode.parentNode.removeChild(folderNode);
157
+ }
158
+ else {
159
+ // Default value node found, let's remove it
160
+ folderNode.removeChild(defaultValueNode);
161
+ }
162
+ return { isFieldFound: true, xml: doc.toString() };
163
+ }
164
+ }
165
+ return { isFieldFound: false };
166
+ }
167
+ async uploadDefaultColumnValuesXml(webUrl, listServerRelUrl, xml) {
168
+ const requestOptions = {
169
+ url: `${webUrl}/_api/Web/GetFileByServerRelativePath(decodedUrl='${formatting.encodeQueryParameter(listServerRelUrl + '/Forms/client_LocationBasedDefaults.html')}')/$value`,
170
+ headers: {
171
+ accept: 'application/json;odata=nometadata',
172
+ 'content-type': 'text/plain'
173
+ },
174
+ responseType: 'json',
175
+ data: xml
176
+ };
177
+ await request.put(requestOptions);
178
+ }
179
+ }
180
+ export default new SpoListDefaultValueRemoveCommand();
181
+ //# sourceMappingURL=list-defaultvalue-remove.js.map