@pnp/cli-microsoft365 10.8.0-beta.a51d886 → 10.8.0

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 (60) hide show
  1. package/.eslintrc.cjs +2 -1
  2. package/README.md +3 -1
  3. package/allCommands.json +1 -1
  4. package/allCommandsFull.json +1 -1
  5. package/dist/cli/cli.js +1 -1
  6. package/dist/config.js +1 -0
  7. package/dist/m365/adaptivecard/commands/adaptivecard-send.js +54 -67
  8. package/dist/m365/app/commands/app-get.js +5 -2
  9. package/dist/m365/app/commands/app-open.js +9 -22
  10. package/dist/m365/app/commands/permission/permission-add.js +18 -30
  11. package/dist/m365/app/commands/permission/permission-list.js +5 -2
  12. package/dist/m365/base/AppCommand.js +9 -25
  13. package/dist/m365/booking/commands/business/business-get.js +18 -25
  14. package/dist/m365/cli/commands/app/app-reconsent.js +103 -0
  15. package/dist/m365/cli/commands.js +1 -0
  16. package/dist/m365/context/commands/context-remove.js +12 -25
  17. package/dist/m365/context/commands/option/option-remove.js +11 -25
  18. package/dist/m365/entra/commands/organization/organization-list.js +51 -0
  19. package/dist/m365/entra/commands.js +1 -0
  20. package/dist/m365/graph/commands/directoryextension/directoryextension-list.js +74 -0
  21. package/dist/m365/graph/commands/openextension/openextension-set.js +107 -0
  22. package/dist/m365/graph/commands.js +2 -0
  23. package/dist/m365/spe/commands/container/container-add.js +85 -0
  24. package/dist/m365/spe/commands/container/container-list.js +2 -9
  25. package/dist/m365/spe/commands/container/container-recyclebinitem-list.js +62 -0
  26. package/dist/m365/spe/commands/container/container-remove.js +99 -0
  27. package/dist/m365/spe/commands/containertype/containertype-add.js +11 -11
  28. package/dist/m365/spe/commands/containertype/containertype-get.js +28 -32
  29. package/dist/m365/spe/commands/containertype/containertype-list.js +14 -4
  30. package/dist/m365/spe/commands/containertype/containertype-remove.js +81 -0
  31. package/dist/m365/spe/commands.js +5 -1
  32. package/dist/m365/spo/commands/list/list-get.js +12 -6
  33. package/dist/m365/spp/commands/model/model-apply.js +130 -0
  34. package/dist/m365/spp/commands/model/model-get.js +7 -24
  35. package/dist/m365/spp/commands/model/model-list.js +1 -1
  36. package/dist/m365/spp/commands/model/model-remove.js +1 -1
  37. package/dist/m365/spp/commands.js +1 -0
  38. package/dist/utils/entraServicePrincipal.js +11 -0
  39. package/dist/utils/formatting.js +12 -0
  40. package/dist/utils/spe.js +77 -0
  41. package/dist/utils/spo.js +0 -18
  42. package/dist/utils/spp.js +59 -1
  43. package/dist/utils/zod.js +26 -1
  44. package/docs/docs/cmd/adaptivecard/adaptivecard-send.mdx +1 -1
  45. package/docs/docs/cmd/cli/app/app-reconsent.mdx +63 -0
  46. package/docs/docs/cmd/entra/organization/organization-list.mdx +154 -0
  47. package/docs/docs/cmd/graph/directoryextension/directoryextension-list.mdx +135 -0
  48. package/docs/docs/cmd/graph/openextension/openextension-set.mdx +97 -0
  49. package/docs/docs/cmd/spe/container/container-activate.mdx +0 -2
  50. package/docs/docs/cmd/spe/container/container-add.mdx +128 -0
  51. package/docs/docs/cmd/spe/container/container-recyclebinitem-list.mdx +96 -0
  52. package/docs/docs/cmd/spe/container/container-remove.mdx +65 -0
  53. package/docs/docs/cmd/spe/containertype/containertype-add.mdx +9 -1
  54. package/docs/docs/cmd/spe/containertype/containertype-get.mdx +8 -0
  55. package/docs/docs/cmd/spe/containertype/containertype-list.mdx +8 -0
  56. package/docs/docs/cmd/spe/containertype/containertype-remove.mdx +52 -0
  57. package/docs/docs/cmd/spo/list/list-get.mdx +12 -3
  58. package/docs/docs/cmd/spp/model/model-apply.mdx +79 -0
  59. package/package.json +3 -3
  60. package/dist/m365/spe/ContainerProperties.js +0 -2
@@ -3,14 +3,15 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
3
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
4
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
5
  };
6
- var _SpeContainertypeGetCommand_instances, _SpeContainertypeGetCommand_initTelemetry, _SpeContainertypeGetCommand_initOptions, _SpeContainertypeGetCommand_initOptionSets, _SpeContainertypeGetCommand_initValidators, _SpeContainertypeGetCommand_initTypes;
6
+ var _SpeContainerTypeGetCommand_instances, _SpeContainerTypeGetCommand_initTelemetry, _SpeContainerTypeGetCommand_initOptions, _SpeContainerTypeGetCommand_initOptionSets, _SpeContainerTypeGetCommand_initValidators, _SpeContainerTypeGetCommand_initTypes;
7
7
  import config from '../../../../config.js';
8
8
  import request from '../../../../request.js';
9
+ import { spe } from '../../../../utils/spe.js';
9
10
  import { spo } from '../../../../utils/spo.js';
10
11
  import { validation } from '../../../../utils/validation.js';
11
12
  import SpoCommand from '../../../base/SpoCommand.js';
12
13
  import commands from '../../commands.js';
13
- class SpeContainertypeGetCommand extends SpoCommand {
14
+ class SpeContainerTypeGetCommand extends SpoCommand {
14
15
  get name() {
15
16
  return commands.CONTAINERTYPE_GET;
16
17
  }
@@ -19,85 +20,80 @@ class SpeContainertypeGetCommand extends SpoCommand {
19
20
  }
20
21
  constructor() {
21
22
  super();
22
- _SpeContainertypeGetCommand_instances.add(this);
23
- __classPrivateFieldGet(this, _SpeContainertypeGetCommand_instances, "m", _SpeContainertypeGetCommand_initTelemetry).call(this);
24
- __classPrivateFieldGet(this, _SpeContainertypeGetCommand_instances, "m", _SpeContainertypeGetCommand_initOptions).call(this);
25
- __classPrivateFieldGet(this, _SpeContainertypeGetCommand_instances, "m", _SpeContainertypeGetCommand_initValidators).call(this);
26
- __classPrivateFieldGet(this, _SpeContainertypeGetCommand_instances, "m", _SpeContainertypeGetCommand_initOptionSets).call(this);
27
- __classPrivateFieldGet(this, _SpeContainertypeGetCommand_instances, "m", _SpeContainertypeGetCommand_initTypes).call(this);
23
+ _SpeContainerTypeGetCommand_instances.add(this);
24
+ __classPrivateFieldGet(this, _SpeContainerTypeGetCommand_instances, "m", _SpeContainerTypeGetCommand_initTelemetry).call(this);
25
+ __classPrivateFieldGet(this, _SpeContainerTypeGetCommand_instances, "m", _SpeContainerTypeGetCommand_initOptions).call(this);
26
+ __classPrivateFieldGet(this, _SpeContainerTypeGetCommand_instances, "m", _SpeContainerTypeGetCommand_initValidators).call(this);
27
+ __classPrivateFieldGet(this, _SpeContainerTypeGetCommand_instances, "m", _SpeContainerTypeGetCommand_initOptionSets).call(this);
28
+ __classPrivateFieldGet(this, _SpeContainerTypeGetCommand_instances, "m", _SpeContainerTypeGetCommand_initTypes).call(this);
28
29
  }
29
30
  async commandAction(logger, args) {
30
31
  try {
31
32
  const spoAdminUrl = await spo.getSpoAdminUrl(logger, this.debug);
32
- if (this.verbose) {
33
- await logger.logToStderr(`Getting the Container type...`);
34
- }
35
33
  const containerTypeId = await this.getContainerTypeId(args.options, spoAdminUrl, logger);
36
- const allContainerTypes = await this.getContainerTypeById(containerTypeId, spoAdminUrl, logger);
37
- await logger.log(allContainerTypes);
34
+ const containerType = await this.getContainerTypeById(containerTypeId, spoAdminUrl, logger);
35
+ await logger.log(containerType);
38
36
  }
39
37
  catch (err) {
40
- this.handleRejectedPromise(err);
38
+ this.handleRejectedODataJsonPromise(err);
41
39
  }
42
40
  }
43
41
  async getContainerTypeById(containerTypeId, spoAdminUrl, logger) {
44
- const formDigestInfo = await spo.ensureFormDigest(spoAdminUrl, logger, undefined, this.debug);
42
+ if (this.verbose) {
43
+ await logger.logToStderr(`Getting the Container type...`);
44
+ }
45
45
  const requestOptions = {
46
46
  url: `${spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
47
47
  headers: {
48
- 'X-RequestDigest': formDigestInfo.FormDigestValue
48
+ accept: 'application/json;odata=nometadata'
49
49
  },
50
+ responseType: 'json',
50
51
  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="49" ObjectPathId="48" /><Method Name="GetSPOContainerTypeById" Id="50" ObjectPathId="48"><Parameters><Parameter Type="Guid">{${containerTypeId}}</Parameter><Parameter Type="Enum">1</Parameter></Parameters></Method></Actions><ObjectPaths><Constructor Id="48" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" /></ObjectPaths></Request>`
51
52
  };
52
53
  const res = await request.post(requestOptions);
53
- const json = JSON.parse(res);
54
- const response = json[0];
54
+ const response = res[0];
55
55
  if (response.ErrorInfo) {
56
56
  throw response.ErrorInfo.ErrorMessage;
57
57
  }
58
- const containerTypes = json[json.length - 1];
58
+ const containerTypes = res[res.length - 1];
59
59
  return containerTypes;
60
60
  }
61
61
  async getContainerTypeId(options, spoAdminUrl, logger) {
62
62
  if (options.id) {
63
63
  return options.id;
64
64
  }
65
- const containerTypes = await spo.getAllContainerTypes(spoAdminUrl, logger, this.debug);
66
- // Get id of the container type by name
67
- const containerType = containerTypes.find(c => c.DisplayName === options.name);
68
- if (!containerType) {
69
- throw new Error(`Container type with name ${options.name} not found`);
65
+ if (this.verbose) {
66
+ await logger.logToStderr(`Retrieving container type id for container type '${options.containerTypeName}'...`);
70
67
  }
71
- const match = containerType.ContainerTypeId.match(/\/Guid\(([^)]+)\)\//);
72
- return match[1];
68
+ return spe.getContainerTypeIdByName(spoAdminUrl, options.name);
73
69
  }
74
70
  }
75
- _SpeContainertypeGetCommand_instances = new WeakSet(), _SpeContainertypeGetCommand_initTelemetry = function _SpeContainertypeGetCommand_initTelemetry() {
71
+ _SpeContainerTypeGetCommand_instances = new WeakSet(), _SpeContainerTypeGetCommand_initTelemetry = function _SpeContainerTypeGetCommand_initTelemetry() {
76
72
  this.telemetry.push((args) => {
77
73
  Object.assign(this.telemetryProperties, {
78
74
  id: typeof args.options.id !== 'undefined',
79
75
  name: typeof args.options.name !== 'undefined'
80
76
  });
81
77
  });
82
- }, _SpeContainertypeGetCommand_initOptions = function _SpeContainertypeGetCommand_initOptions() {
78
+ }, _SpeContainerTypeGetCommand_initOptions = function _SpeContainerTypeGetCommand_initOptions() {
83
79
  this.options.unshift({
84
80
  option: '-i, --id [id]'
85
81
  }, {
86
82
  option: '-n, --name [name]'
87
83
  });
88
- }, _SpeContainertypeGetCommand_initOptionSets = function _SpeContainertypeGetCommand_initOptionSets() {
84
+ }, _SpeContainerTypeGetCommand_initOptionSets = function _SpeContainerTypeGetCommand_initOptionSets() {
89
85
  this.optionSets.push({
90
86
  options: ['id', 'name']
91
87
  });
92
- }, _SpeContainertypeGetCommand_initValidators = function _SpeContainertypeGetCommand_initValidators() {
88
+ }, _SpeContainerTypeGetCommand_initValidators = function _SpeContainerTypeGetCommand_initValidators() {
93
89
  this.validators.push(async (args) => {
94
90
  if (args.options.id && !validation.isValidGuid(args.options.id)) {
95
91
  return `${args.options.id} is not a valid GUID`;
96
92
  }
97
93
  return true;
98
94
  });
99
- }, _SpeContainertypeGetCommand_initTypes = function _SpeContainertypeGetCommand_initTypes() {
95
+ }, _SpeContainerTypeGetCommand_initTypes = function _SpeContainerTypeGetCommand_initTypes() {
100
96
  this.types.string.push('id', 'name');
101
97
  };
102
- export default new SpeContainertypeGetCommand();
98
+ export default new SpeContainerTypeGetCommand();
103
99
  //# sourceMappingURL=containertype-get.js.map
@@ -1,7 +1,8 @@
1
1
  import SpoCommand from '../../../base/SpoCommand.js';
2
2
  import commands from '../../commands.js';
3
+ import { spe } from '../../../../utils/spe.js';
3
4
  import { spo } from '../../../../utils/spo.js';
4
- class SpeContainertypeListCommand extends SpoCommand {
5
+ class SpeContainerTypeListCommand extends SpoCommand {
5
6
  get name() {
6
7
  return commands.CONTAINERTYPE_LIST;
7
8
  }
@@ -17,13 +18,22 @@ class SpeContainertypeListCommand extends SpoCommand {
17
18
  if (this.verbose) {
18
19
  await logger.logToStderr(`Retrieving list of Container types...`);
19
20
  }
20
- const allContainerTypes = await spo.getAllContainerTypes(spoAdminUrl, logger, this.debug);
21
- await logger.log(allContainerTypes);
21
+ const allContainerTypes = await spe.getAllContainerTypes(spoAdminUrl);
22
+ // The following conversion is done in order not to make breaking changes
23
+ const result = allContainerTypes.map(ct => ({
24
+ _ObjectType_: 'Microsoft.Online.SharePoint.TenantAdministration.SPContainerTypeProperties',
25
+ ...ct,
26
+ AzureSubscriptionId: `/Guid(${ct.AzureSubscriptionId})/`,
27
+ ContainerTypeId: `/Guid(${ct.ContainerTypeId})/`,
28
+ OwningAppId: `/Guid(${ct.OwningAppId})/`,
29
+ OwningTenantId: `/Guid(${ct.OwningTenantId})/`
30
+ }));
31
+ await logger.log(result);
22
32
  }
23
33
  catch (err) {
24
34
  this.handleRejectedPromise(err);
25
35
  }
26
36
  }
27
37
  }
28
- export default new SpeContainertypeListCommand();
38
+ export default new SpeContainerTypeListCommand();
29
39
  //# sourceMappingURL=containertype-list.js.map
@@ -0,0 +1,81 @@
1
+ import { globalOptionsZod } from '../../../../Command.js';
2
+ import { z } from 'zod';
3
+ import { zod } from '../../../../utils/zod.js';
4
+ import SpoCommand from '../../../base/SpoCommand.js';
5
+ import commands from '../../commands.js';
6
+ import { spo } from '../../../../utils/spo.js';
7
+ import { spe } from '../../../../utils/spe.js';
8
+ import { cli } from '../../../../cli/cli.js';
9
+ import { validation } from '../../../../utils/validation.js';
10
+ import request from '../../../../request.js';
11
+ import config from '../../../../config.js';
12
+ const options = globalOptionsZod
13
+ .extend({
14
+ id: zod.alias('i', z.string()
15
+ .refine(id => validation.isValidGuid(id), id => ({
16
+ message: `'${id}' is not a valid GUID.`
17
+ }))
18
+ .optional()),
19
+ name: zod.alias('n', z.string().optional()),
20
+ force: zod.alias('f', z.boolean().optional())
21
+ })
22
+ .strict();
23
+ class SpeContainerTypeRemoveCommand extends SpoCommand {
24
+ get name() {
25
+ return commands.CONTAINERTYPE_REMOVE;
26
+ }
27
+ get description() {
28
+ return 'Remove a specific container type';
29
+ }
30
+ get schema() {
31
+ return options;
32
+ }
33
+ getRefinedSchema(schema) {
34
+ return schema
35
+ .refine(options => [options.id, options.name].filter(o => o !== undefined).length === 1, {
36
+ message: 'Use one of the following options: id, name.'
37
+ });
38
+ }
39
+ async commandAction(logger, args) {
40
+ if (!args.options.force) {
41
+ const result = await cli.promptForConfirmation({ message: `Are you sure you want to remove container type ${args.options.id || args.options.name}?` });
42
+ if (!result) {
43
+ return;
44
+ }
45
+ }
46
+ try {
47
+ const spoAdminUrl = await spo.getSpoAdminUrl(logger, this.verbose);
48
+ const containerTypeId = await this.getContainerTypeId(args.options, spoAdminUrl, logger);
49
+ const formDigestInfo = await spo.ensureFormDigest(spoAdminUrl, logger, undefined, this.debug);
50
+ if (this.verbose) {
51
+ await logger.logToStderr(`Removing container type ${args.options.id || args.options.name}...`);
52
+ }
53
+ const requestOptions = {
54
+ url: `${spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
55
+ headers: {
56
+ 'X-RequestDigest': formDigestInfo.FormDigestValue
57
+ },
58
+ responseType: 'json',
59
+ 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="7" ObjectPathId="6" /><Method Name="RemoveSPOContainerType" Id="8" ObjectPathId="6"><Parameters><Parameter TypeId="{b66ab1ca-fd51-44f9-8cfc-01f5c2a21f99}"><Property Name="ContainerTypeId" Type="Guid">{${containerTypeId}}</Property></Parameter></Parameters></Method></Actions><ObjectPaths><Constructor Id="6" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" /></ObjectPaths></Request>`
60
+ };
61
+ const result = await request.post(requestOptions);
62
+ if (result[0].ErrorInfo) {
63
+ throw result[0].ErrorInfo.ErrorMessage;
64
+ }
65
+ }
66
+ catch (err) {
67
+ this.handleRejectedODataJsonPromise(err);
68
+ }
69
+ }
70
+ async getContainerTypeId(options, spoAdminUrl, logger) {
71
+ if (options.id) {
72
+ return options.id;
73
+ }
74
+ if (this.verbose) {
75
+ await logger.logToStderr(`Retrieving container type id for container type '${options.name}'...`);
76
+ }
77
+ return spe.getContainerTypeIdByName(spoAdminUrl, options.name);
78
+ }
79
+ }
80
+ export default new SpeContainerTypeRemoveCommand();
81
+ //# sourceMappingURL=containertype-remove.js.map
@@ -1,11 +1,15 @@
1
1
  const prefix = 'spe';
2
2
  export default {
3
3
  CONTAINER_ACTIVATE: `${prefix} container activate`,
4
+ CONTAINER_ADD: `${prefix} container add`,
4
5
  CONTAINER_GET: `${prefix} container get`,
5
6
  CONTAINER_LIST: `${prefix} container list`,
7
+ CONTAINER_REMOVE: `${prefix} container remove`,
6
8
  CONTAINER_PERMISSION_LIST: `${prefix} container permission list`,
9
+ CONTAINER_RECYCLEBINITEM_LIST: `${prefix} container recyclebinitem list`,
7
10
  CONTAINERTYPE_ADD: `${prefix} containertype add`,
8
11
  CONTAINERTYPE_GET: `${prefix} containertype get`,
9
- CONTAINERTYPE_LIST: `${prefix} containertype list`
12
+ CONTAINERTYPE_LIST: `${prefix} containertype list`,
13
+ CONTAINERTYPE_REMOVE: `${prefix} containertype remove`
10
14
  };
11
15
  //# sourceMappingURL=commands.js.map
@@ -43,6 +43,9 @@ class SpoListGetCommand extends SpoCommand {
43
43
  const listServerRelativeUrl = urlUtil.getServerRelativePath(args.options.webUrl, args.options.url);
44
44
  requestUrl += `GetList('${formatting.encodeQueryParameter(listServerRelativeUrl)}')`;
45
45
  }
46
+ else if (args.options.default) {
47
+ requestUrl += `DefaultDocumentLibrary`;
48
+ }
46
49
  const fieldsProperties = this.formatSelectProperties(args.options.properties, args.options.withPermissions);
47
50
  const queryParams = [];
48
51
  if (fieldsProperties.selectProperties.length > 0) {
@@ -113,11 +116,12 @@ class SpoListGetCommand extends SpoCommand {
113
116
  _SpoListGetCommand_instances = new WeakSet(), _SpoListGetCommand_initTelemetry = function _SpoListGetCommand_initTelemetry() {
114
117
  this.telemetry.push((args) => {
115
118
  Object.assign(this.telemetryProperties, {
116
- id: (!(!args.options.id)).toString(),
117
- title: (!(!args.options.title)).toString(),
118
- url: (!(!args.options.url)).toString(),
119
- properties: (!(!args.options.properties)).toString(),
120
- withPermissions: typeof args.options.withPermissions !== 'undefined'
119
+ id: typeof args.options.id !== 'undefined',
120
+ title: typeof args.options.title !== 'undefined',
121
+ url: typeof args.options.url !== 'undefined',
122
+ properties: typeof args.options.properties !== 'undefined',
123
+ withPermissions: !!args.options.withPermissions,
124
+ default: !!args.options.default
121
125
  });
122
126
  });
123
127
  }, _SpoListGetCommand_initOptions = function _SpoListGetCommand_initOptions() {
@@ -129,6 +133,8 @@ _SpoListGetCommand_instances = new WeakSet(), _SpoListGetCommand_initTelemetry =
129
133
  option: '-t, --title [title]'
130
134
  }, {
131
135
  option: '--url [url]'
136
+ }, {
137
+ option: '--default'
132
138
  }, {
133
139
  option: '-p, --properties [properties]'
134
140
  }, {
@@ -148,7 +154,7 @@ _SpoListGetCommand_instances = new WeakSet(), _SpoListGetCommand_initTelemetry =
148
154
  return true;
149
155
  });
150
156
  }, _SpoListGetCommand_initOptionSets = function _SpoListGetCommand_initOptionSets() {
151
- this.optionSets.push({ options: ['id', 'title', 'url'] });
157
+ this.optionSets.push({ options: ['id', 'title', 'url', 'default'] });
152
158
  };
153
159
  export default new SpoListGetCommand();
154
160
  //# sourceMappingURL=list-get.js.map
@@ -0,0 +1,130 @@
1
+ import request from '../../../../request.js';
2
+ import { formatting } from '../../../../utils/formatting.js';
3
+ import { spp } from '../../../../utils/spp.js';
4
+ import { urlUtil } from '../../../../utils/urlUtil.js';
5
+ import { validation } from '../../../../utils/validation.js';
6
+ import SpoCommand from '../../../base/SpoCommand.js';
7
+ import commands from '../../commands.js';
8
+ import { z } from 'zod';
9
+ import { globalOptionsZod } from '../../../../Command.js';
10
+ import { zod } from '../../../../utils/zod.js';
11
+ const options = globalOptionsZod
12
+ .extend({
13
+ contentCenterUrl: zod.alias('c', z.string()
14
+ .refine(url => validation.isValidSharePointUrl(url) === true, url => ({
15
+ message: `'${url}' is not a valid SharePoint Online site URL.`
16
+ }))),
17
+ webUrl: zod.alias('u', z.string()
18
+ .refine(url => validation.isValidSharePointUrl(url) === true, url => ({
19
+ message: `'${url}' is not a valid SharePoint Online site URL.`
20
+ }))),
21
+ id: zod.alias('i', z.string()
22
+ .refine(id => validation.isValidGuid(id) === true, id => ({
23
+ message: `${id} is not a valid GUID.`
24
+ })).optional()),
25
+ title: zod.alias('t', z.string()).optional(),
26
+ listTitle: z.string().optional(),
27
+ listId: z.string()
28
+ .refine(listId => validation.isValidGuid(listId) === true, listId => ({
29
+ message: `${listId} is not a valid GUID.`
30
+ })).optional(),
31
+ listUrl: z.string().optional(),
32
+ viewOption: z.enum(['NewViewAsDefault', 'DoNotChangeDefault', 'TileViewAsDefault']).optional()
33
+ })
34
+ .strict();
35
+ class SppModelApplyCommand extends SpoCommand {
36
+ get name() {
37
+ return commands.MODEL_APPLY;
38
+ }
39
+ get description() {
40
+ return 'Applies (or syncs) a trained document understanding model to a document library';
41
+ }
42
+ get schema() {
43
+ return options;
44
+ }
45
+ getRefinedSchema(schema) {
46
+ return schema
47
+ .refine(options => [options.id, options.title].filter(x => x !== undefined).length === 1, {
48
+ message: `Specify exactly one of the following options: 'id' or 'title'.`
49
+ })
50
+ .refine(options => [options.listTitle, options.listId, options.listUrl].filter(x => x !== undefined).length === 1, {
51
+ message: `Specify exactly one of the following options: 'listTitle', 'listId' or 'listUrl'.`
52
+ });
53
+ }
54
+ async commandAction(logger, args) {
55
+ try {
56
+ const contentCenterUrl = urlUtil.removeTrailingSlashes(args.options.contentCenterUrl);
57
+ await spp.assertSiteIsContentCenter(contentCenterUrl, logger, this.verbose);
58
+ let model = null;
59
+ if (args.options.title) {
60
+ model = await spp.getModelByTitle(contentCenterUrl, args.options.title, logger, this.verbose);
61
+ }
62
+ else {
63
+ model = await spp.getModelById(contentCenterUrl, args.options.id, logger, this.verbose);
64
+ }
65
+ if (this.verbose) {
66
+ await logger.log(`Retrieving list information...`);
67
+ }
68
+ const listInstance = await this.getListInfo(args.options.webUrl, args.options.listId, args.options.listTitle, args.options.listUrl);
69
+ if (listInstance.BaseType !== 1) {
70
+ throw `The specified list is not a document library.`;
71
+ }
72
+ if (this.verbose) {
73
+ await logger.log(`Applying model '${model.ModelName}' to document library '${listInstance.RootFolder.ServerRelativeUrl}'...`);
74
+ }
75
+ const requestOptions = {
76
+ url: `${contentCenterUrl}/_api/machinelearning/publications`,
77
+ headers: {
78
+ accept: 'application/json;odata=nometadata',
79
+ 'Content-Type': 'application/json;odata=verbose'
80
+ },
81
+ responseType: 'json',
82
+ data: {
83
+ __metadata: { type: 'Microsoft.Office.Server.ContentCenter.SPMachineLearningPublicationsEntityData' },
84
+ Publications: {
85
+ results: [
86
+ {
87
+ ModelUniqueId: model.UniqueId,
88
+ TargetSiteUrl: args.options.webUrl,
89
+ TargetWebServerRelativeUrl: urlUtil.getServerRelativeSiteUrl(args.options.webUrl),
90
+ TargetLibraryServerRelativeUrl: listInstance.RootFolder.ServerRelativeUrl,
91
+ ViewOption: args.options.viewOption ?? "NewViewAsDefault"
92
+ }
93
+ ]
94
+ }
95
+ }
96
+ };
97
+ const result = await request.post(requestOptions);
98
+ const resultDetails = result.Details;
99
+ if (resultDetails && resultDetails[0]?.ErrorMessage) {
100
+ throw resultDetails[0].ErrorMessage;
101
+ }
102
+ }
103
+ catch (err) {
104
+ this.handleRejectedODataJsonPromise(err);
105
+ }
106
+ }
107
+ getListInfo(webUrl, listId, listTitle, listUrl) {
108
+ let requestUrl = `${webUrl}/_api/web`;
109
+ if (listId) {
110
+ requestUrl += `/lists(guid'${formatting.encodeQueryParameter(listId)}')`;
111
+ }
112
+ else if (listTitle) {
113
+ requestUrl += `/lists/getByTitle('${formatting.encodeQueryParameter(listTitle)}')`;
114
+ }
115
+ else if (listUrl) {
116
+ const listServerRelativeUrl = urlUtil.getServerRelativePath(webUrl, listUrl);
117
+ requestUrl += `/GetList('${formatting.encodeQueryParameter(listServerRelativeUrl)}')`;
118
+ }
119
+ const requestOptions = {
120
+ url: `${requestUrl}?$select=BaseType,RootFolder/ServerRelativeUrl&$expand=RootFolder`,
121
+ headers: {
122
+ accept: 'application/json;odata=nometadata'
123
+ },
124
+ responseType: 'json'
125
+ };
126
+ return request.get(requestOptions);
127
+ }
128
+ }
129
+ export default new SppModelApplyCommand();
130
+ //# sourceMappingURL=model-apply.js.map
@@ -4,8 +4,6 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
4
4
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
5
  };
6
6
  var _SppModelGetCommand_instances, _SppModelGetCommand_initTelemetry, _SppModelGetCommand_initOptions, _SppModelGetCommand_initValidators, _SppModelGetCommand_initOptionSets, _SppModelGetCommand_initTypes;
7
- import request from '../../../../request.js';
8
- import { formatting } from '../../../../utils/formatting.js';
9
7
  import { odata } from '../../../../utils/odata.js';
10
8
  import { spp } from '../../../../utils/spp.js';
11
9
  import { urlUtil } from '../../../../utils/urlUtil.js';
@@ -30,34 +28,19 @@ class SppModelGetCommand extends SpoCommand {
30
28
  }
31
29
  async commandAction(logger, args) {
32
30
  try {
33
- if (this.verbose) {
34
- await logger.log(`Retrieving model information from ${args.options.siteUrl}...`);
35
- }
36
31
  const siteUrl = urlUtil.removeTrailingSlashes(args.options.siteUrl);
37
- await spp.assertSiteIsContentCenter(siteUrl);
38
- let requestUrl = `${siteUrl}/_api/machinelearning/models/`;
32
+ await spp.assertSiteIsContentCenter(siteUrl, logger, this.verbose);
33
+ let result = null;
39
34
  if (args.options.title) {
40
- let requestTitle = args.options.title.toLowerCase();
41
- if (!requestTitle.endsWith('.classifier')) {
42
- requestTitle += '.classifier';
43
- }
44
- requestUrl += `getbytitle('${formatting.encodeQueryParameter(requestTitle)}')`;
35
+ result = await spp.getModelByTitle(siteUrl, args.options.title, logger, this.verbose);
45
36
  }
46
37
  else {
47
- requestUrl += `getbyuniqueid('${args.options.id}')`;
48
- }
49
- const requestOptions = {
50
- url: requestUrl,
51
- headers: {
52
- accept: 'application/json;odata=nometadata'
53
- },
54
- responseType: 'json'
55
- };
56
- const result = await request.get(requestOptions);
57
- if (result['odata.null'] === true) {
58
- throw 'Model not found.';
38
+ result = await spp.getModelById(siteUrl, args.options.id, logger, this.verbose);
59
39
  }
60
40
  if (args.options.withPublications) {
41
+ if (this.verbose) {
42
+ await logger.log(`Retrieving publications for model...`);
43
+ }
61
44
  result.Publications = await odata.getAllItems(`${siteUrl}/_api/machinelearning/publications/getbymodeluniqueid('${result.UniqueId}')`);
62
45
  }
63
46
  await logger.log({
@@ -33,7 +33,7 @@ class SppModelListCommand extends SpoCommand {
33
33
  await logger.log(`Retrieving models from ${args.options.siteUrl}...`);
34
34
  }
35
35
  const siteUrl = urlUtil.removeTrailingSlashes(args.options.siteUrl);
36
- await spp.assertSiteIsContentCenter(siteUrl);
36
+ await spp.assertSiteIsContentCenter(siteUrl, logger, this.verbose);
37
37
  const result = await odata.getAllItems(`${siteUrl}/_api/machinelearning/models`);
38
38
  await logger.log(result);
39
39
  }
@@ -40,7 +40,7 @@ class SppModelRemoveCommand extends SpoCommand {
40
40
  await logger.log(`Removing model from ${args.options.siteUrl}...`);
41
41
  }
42
42
  const siteUrl = urlUtil.removeTrailingSlashes(args.options.siteUrl);
43
- await spp.assertSiteIsContentCenter(siteUrl);
43
+ await spp.assertSiteIsContentCenter(siteUrl, logger, this.verbose);
44
44
  let requestUrl = `${siteUrl}/_api/machinelearning/models/`;
45
45
  if (args.options.title) {
46
46
  let requestTitle = args.options.title.toLowerCase();
@@ -1,6 +1,7 @@
1
1
  const prefix = 'spp';
2
2
  export default {
3
3
  CONTENTCENTER_LIST: `${prefix} contentcenter list`,
4
+ MODEL_APPLY: `${prefix} model apply`,
4
5
  MODEL_GET: `${prefix} model get`,
5
6
  MODEL_LIST: `${prefix} model list`,
6
7
  MODEL_REMOVE: `${prefix} model remove`
@@ -41,6 +41,17 @@ export const entraServicePrincipal = {
41
41
  return await cli.handleMultipleResultsFound(`Multiple service principals with name '${appName}' found in Microsoft Entra ID.`, resultAsKeyValuePair);
42
42
  }
43
43
  return apps[0];
44
+ },
45
+ /**
46
+ * Get all available service principals.
47
+ * @param properties Comma-separated list of properties to include in the response.
48
+ */
49
+ async getServicePrincipals(properties) {
50
+ let url = `https://graph.microsoft.com/v1.0/servicePrincipals`;
51
+ if (properties) {
52
+ url += `?$select=${properties}`;
53
+ }
54
+ return odata.getAllItems(url);
44
55
  }
45
56
  };
46
57
  //# sourceMappingURL=entraServicePrincipal.js.map
@@ -177,6 +177,18 @@ export const formatting = {
177
177
  resultAsKeyValuePair[obj[key]] = obj;
178
178
  });
179
179
  return resultAsKeyValuePair;
180
+ },
181
+ /**
182
+ * Extracts the GUID from a string in CSOM format.
183
+ * @param str The string to extract the GUID from
184
+ * @description The string should be in the format /Guid(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)/
185
+ * @returns The extracted GUID or the original string if no match is found
186
+ * @example /Guid(eae15efb-ac09-49b9-8906-e579efd622e4)/ => eae15efb-ac09-49b9-8906-e579efd622e4
187
+ */
188
+ extractCsomGuid(str) {
189
+ const guidPattern = /\/Guid\(([0-9a-f-]+)\)\//i;
190
+ const match = str.match(guidPattern);
191
+ return match ? match[1] : str;
180
192
  }
181
193
  };
182
194
  //# sourceMappingURL=formatting.js.map
@@ -0,0 +1,77 @@
1
+ import request from '../request.js';
2
+ import { formatting } from './formatting.js';
3
+ import { cli } from '../cli/cli.js';
4
+ import config from '../config.js';
5
+ import { odata } from './odata.js';
6
+ const graphResource = 'https://graph.microsoft.com';
7
+ export const spe = {
8
+ /**
9
+ * Get all container types.
10
+ * @param spoAdminUrl The URL of the SharePoint Online admin center site (e.g. https://contoso-admin.sharepoint.com)
11
+ * @returns Array of container types
12
+ */
13
+ async getAllContainerTypes(spoAdminUrl) {
14
+ const requestOptions = {
15
+ url: `${spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
16
+ headers: {
17
+ accept: 'application/json;odata=nometadata'
18
+ },
19
+ responseType: 'json',
20
+ 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>`
21
+ };
22
+ const json = await request.post(requestOptions);
23
+ const response = json[0];
24
+ if (response.ErrorInfo) {
25
+ throw new Error(response.ErrorInfo.ErrorMessage);
26
+ }
27
+ const containerTypes = json[json.length - 1];
28
+ // Format the response to remove CSOM GUIDs and convert them to real GUIDs
29
+ containerTypes.forEach(ct => {
30
+ delete ct._ObjectType_;
31
+ ct.AzureSubscriptionId = formatting.extractCsomGuid(ct.AzureSubscriptionId);
32
+ ct.ContainerTypeId = formatting.extractCsomGuid(ct.ContainerTypeId);
33
+ ct.OwningAppId = formatting.extractCsomGuid(ct.OwningAppId);
34
+ ct.OwningTenantId = formatting.extractCsomGuid(ct.OwningTenantId);
35
+ });
36
+ return containerTypes;
37
+ },
38
+ /**
39
+ * Get the ID of a container type by its name.
40
+ * @param spoAdminUrl SharePoint Online admin center URL (e.g. https://contoso-admin.sharepoint.com)
41
+ * @param name Name of the container type to search for
42
+ * @returns ID of the container type
43
+ */
44
+ async getContainerTypeIdByName(spoAdminUrl, name) {
45
+ const allContainerTypes = await this.getAllContainerTypes(spoAdminUrl);
46
+ const containerTypes = allContainerTypes.filter(ct => ct.DisplayName.toLowerCase() === name.toLowerCase());
47
+ if (containerTypes.length === 0) {
48
+ throw new Error(`The specified container type '${name}' does not exist.`);
49
+ }
50
+ if (containerTypes.length > 1) {
51
+ const containerTypeKeyValuePair = formatting.convertArrayToHashTable('ContainerTypeId', containerTypes);
52
+ const containerType = await cli.handleMultipleResultsFound(`Multiple container types with name '${name}' found.`, containerTypeKeyValuePair);
53
+ return containerType.ContainerTypeId;
54
+ }
55
+ return containerTypes[0].ContainerTypeId;
56
+ },
57
+ /**
58
+ * Get the ID of a container by its name.
59
+ * @param containerTypeId ID of the container type.
60
+ * @param name Name of the container to search for.
61
+ * @returns ID of the container.
62
+ */
63
+ async getContainerIdByName(containerTypeId, name) {
64
+ const containers = await odata.getAllItems(`${graphResource}/v1.0/storage/fileStorage/containers?$filter=containerTypeId eq ${containerTypeId}&$select=id,displayName`);
65
+ const matchingContainers = containers.filter(c => c.displayName.toLowerCase() === name.toLowerCase());
66
+ if (matchingContainers.length === 0) {
67
+ throw new Error(`The specified container '${name}' does not exist.`);
68
+ }
69
+ if (matchingContainers.length > 1) {
70
+ const containerKeyValuePair = formatting.convertArrayToHashTable('id', matchingContainers);
71
+ const container = await cli.handleMultipleResultsFound(`Multiple containers with name '${name}' found.`, containerKeyValuePair);
72
+ return container.id;
73
+ }
74
+ return matchingContainers[0].id;
75
+ }
76
+ };
77
+ //# sourceMappingURL=spe.js.map