@pnp/cli-microsoft365 10.8.0-beta.708bf27 → 10.8.0-beta.a1c69a6
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.
- package/.eslintrc.cjs +2 -1
- package/README.md +3 -1
- package/allCommands.json +1 -1
- package/allCommandsFull.json +1 -1
- package/dist/Auth.js +82 -22
- package/dist/cli/cli.js +1 -1
- package/dist/config.js +1 -0
- package/dist/m365/adaptivecard/commands/adaptivecard-send.js +54 -67
- package/dist/m365/app/commands/app-get.js +5 -2
- package/dist/m365/app/commands/app-open.js +9 -22
- package/dist/m365/app/commands/permission/permission-add.js +18 -30
- package/dist/m365/app/commands/permission/permission-list.js +5 -2
- package/dist/m365/base/AppCommand.js +9 -25
- package/dist/m365/booking/commands/business/business-get.js +18 -25
- package/dist/m365/cli/commands/app/app-reconsent.js +103 -0
- package/dist/m365/cli/commands.js +1 -0
- package/dist/m365/commands/login.js +1 -1
- package/dist/m365/commands/setup.js +1 -2
- package/dist/m365/context/commands/context-remove.js +12 -25
- package/dist/m365/context/commands/option/option-remove.js +11 -25
- package/dist/m365/entra/commands/organization/organization-list.js +51 -0
- package/dist/m365/entra/commands.js +1 -0
- package/dist/m365/graph/commands/directoryextension/directoryextension-list.js +74 -0
- package/dist/m365/graph/commands/openextension/openextension-set.js +107 -0
- package/dist/m365/graph/commands.js +2 -0
- package/dist/m365/spe/commands/container/container-add.js +85 -0
- package/dist/m365/spe/commands/container/container-list.js +2 -9
- package/dist/m365/spe/commands/container/container-permission-list.js +52 -0
- package/dist/m365/spe/commands/container/container-recyclebinitem-list.js +62 -0
- package/dist/m365/spe/commands/container/container-remove.js +99 -0
- package/dist/m365/spe/commands/containertype/containertype-add.js +11 -11
- package/dist/m365/spe/commands/containertype/containertype-get.js +28 -32
- package/dist/m365/spe/commands/containertype/containertype-list.js +14 -4
- package/dist/m365/spe/commands/containertype/containertype-remove.js +81 -0
- package/dist/m365/spe/commands.js +6 -1
- package/dist/m365/spo/commands/list/list-get.js +12 -6
- package/dist/m365/spo/commands/page/page-section-add.js +20 -23
- package/dist/m365/spp/commands/model/model-apply.js +130 -0
- package/dist/m365/spp/commands/model/model-get.js +7 -24
- package/dist/m365/spp/commands/model/model-list.js +1 -1
- package/dist/m365/spp/commands/model/model-remove.js +1 -1
- package/dist/m365/spp/commands.js +1 -0
- package/dist/utils/entraServicePrincipal.js +11 -0
- package/dist/utils/formatting.js +12 -0
- package/dist/utils/spe.js +77 -0
- package/dist/utils/spo.js +0 -18
- package/dist/utils/spp.js +59 -1
- package/dist/utils/zod.js +26 -1
- package/docs/docs/cmd/adaptivecard/adaptivecard-send.mdx +1 -1
- package/docs/docs/cmd/cli/app/app-reconsent.mdx +63 -0
- package/docs/docs/cmd/entra/organization/organization-list.mdx +154 -0
- package/docs/docs/cmd/graph/directoryextension/directoryextension-list.mdx +135 -0
- package/docs/docs/cmd/graph/openextension/openextension-set.mdx +97 -0
- package/docs/docs/cmd/spe/container/container-activate.mdx +0 -2
- package/docs/docs/cmd/spe/container/container-add.mdx +128 -0
- package/docs/docs/cmd/spe/container/container-permission-list.mdx +90 -0
- package/docs/docs/cmd/spe/container/container-recyclebinitem-list.mdx +96 -0
- package/docs/docs/cmd/spe/container/container-remove.mdx +65 -0
- package/docs/docs/cmd/spe/containertype/containertype-add.mdx +9 -1
- package/docs/docs/cmd/spe/containertype/containertype-get.mdx +8 -0
- package/docs/docs/cmd/spe/containertype/containertype-list.mdx +8 -0
- package/docs/docs/cmd/spe/containertype/containertype-remove.mdx +52 -0
- package/docs/docs/cmd/spo/field/field-get.mdx +0 -1
- package/docs/docs/cmd/spo/list/list-get.mdx +12 -3
- package/docs/docs/cmd/spp/model/model-apply.mdx +79 -0
- package/npm-shrinkwrap.json +894 -477
- package/package.json +11 -11
- package/dist/m365/spe/ContainerProperties.js +0 -2
|
@@ -59,19 +59,25 @@ class SpoPageSectionAddCommand extends SpoCommand {
|
|
|
59
59
|
};
|
|
60
60
|
await request.post(requestOptions);
|
|
61
61
|
}
|
|
62
|
-
// get columns
|
|
63
|
-
const columns = canvasContent
|
|
64
|
-
.filter(c => typeof c.controlType === 'undefined');
|
|
65
62
|
// get unique zoneIndex values given each section can have 1 or more
|
|
66
63
|
// columns each assigned to the zoneIndex of the corresponding section
|
|
67
|
-
const zoneIndices =
|
|
64
|
+
const zoneIndices = canvasContent
|
|
65
|
+
// Exclude the vertical section
|
|
66
|
+
.filter(c => c.position)
|
|
68
67
|
.map(c => c.position.zoneIndex)
|
|
69
68
|
.filter((value, index, array) => {
|
|
70
69
|
return array.indexOf(value) === index;
|
|
71
70
|
})
|
|
72
|
-
.sort();
|
|
73
|
-
// zoneIndex
|
|
74
|
-
|
|
71
|
+
.sort((a, b) => a - b);
|
|
72
|
+
// Add a new zoneIndex at the end of the array
|
|
73
|
+
zoneIndices.push(zoneIndices.length > 0 ? zoneIndices[zoneIndices.length - 1] + 1 : 1);
|
|
74
|
+
// get section number. if not specified, get the last section
|
|
75
|
+
let section = args.options.order || zoneIndices.length;
|
|
76
|
+
if (section > zoneIndices.length) {
|
|
77
|
+
section = zoneIndices.length;
|
|
78
|
+
}
|
|
79
|
+
// zoneIndex that represents the section where the web part should be added
|
|
80
|
+
const zoneIndex = zoneIndices[section - 1];
|
|
75
81
|
let zoneId;
|
|
76
82
|
let backgroundControlToAdd = undefined;
|
|
77
83
|
if (args.options.zoneEmphasis && ['image', 'gradient'].includes(args.options.zoneEmphasis.toLowerCase())) {
|
|
@@ -83,11 +89,17 @@ class SpoPageSectionAddCommand extends SpoCommand {
|
|
|
83
89
|
canvasContent.push(backgroundControlToAdd);
|
|
84
90
|
}
|
|
85
91
|
}
|
|
92
|
+
// Increment the zoneIndex of all columns that are greater than or equal to the new zoneIndex
|
|
93
|
+
canvasContent.forEach((c) => {
|
|
94
|
+
if (c.position && c.position.zoneIndex >= zoneIndex) {
|
|
95
|
+
c.position.zoneIndex += 1;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
86
98
|
// get the list of columns to insert based on the selected template
|
|
87
99
|
const columnsToAdd = this.getColumns(zoneIndex, args, zoneId);
|
|
88
100
|
// insert the column in the right place in the array so that
|
|
89
101
|
// it stays sorted ascending by zoneIndex
|
|
90
|
-
let pos = canvasContent.findIndex(c =>
|
|
102
|
+
let pos = canvasContent.findIndex(c => c.position && c.position.zoneIndex >= zoneIndex);
|
|
91
103
|
if (pos === -1) {
|
|
92
104
|
pos = canvasContent.length - 1;
|
|
93
105
|
}
|
|
@@ -109,21 +121,6 @@ class SpoPageSectionAddCommand extends SpoCommand {
|
|
|
109
121
|
this.handleRejectedODataJsonPromise(err);
|
|
110
122
|
}
|
|
111
123
|
}
|
|
112
|
-
getSectionIndex(zoneIndices, order) {
|
|
113
|
-
// zoneIndex of the first column on the page
|
|
114
|
-
const minIndex = zoneIndices.length === 0 ? 0 : zoneIndices[0];
|
|
115
|
-
// zoneIndex of the last column on the page
|
|
116
|
-
const maxIndex = zoneIndices.length === 0 ? 0 : zoneIndices[zoneIndices.length - 1];
|
|
117
|
-
if (!order || order > zoneIndices.length) {
|
|
118
|
-
// no order specified, add section to the end
|
|
119
|
-
return maxIndex === 0 ? 1 : maxIndex * 2;
|
|
120
|
-
}
|
|
121
|
-
// add to the beginning
|
|
122
|
-
if (order === 1) {
|
|
123
|
-
return minIndex / 2;
|
|
124
|
-
}
|
|
125
|
-
return zoneIndices[order - 2] + ((zoneIndices[order - 1] - zoneIndices[order - 2]) / 2);
|
|
126
|
-
}
|
|
127
124
|
getColumns(zoneIndex, args, zoneId) {
|
|
128
125
|
const columns = [];
|
|
129
126
|
let sectionIndex = 1;
|
|
@@ -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
|
|
32
|
+
await spp.assertSiteIsContentCenter(siteUrl, logger, this.verbose);
|
|
33
|
+
let result = null;
|
|
39
34
|
if (args.options.title) {
|
|
40
|
-
|
|
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
|
-
|
|
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();
|
|
@@ -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
|
package/dist/utils/formatting.js
CHANGED
|
@@ -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
|
package/dist/utils/spo.js
CHANGED
|
@@ -53,24 +53,6 @@ export const spo = {
|
|
|
53
53
|
};
|
|
54
54
|
return context;
|
|
55
55
|
},
|
|
56
|
-
async getAllContainerTypes(spoAdminUrl, logger, verbose) {
|
|
57
|
-
const formDigestInfo = await spo.ensureFormDigest(spoAdminUrl, logger, undefined, verbose);
|
|
58
|
-
const requestOptions = {
|
|
59
|
-
url: `${spoAdminUrl}/_vti_bin/client.svc/ProcessQuery`,
|
|
60
|
-
headers: {
|
|
61
|
-
'X-RequestDigest': formDigestInfo.FormDigestValue
|
|
62
|
-
},
|
|
63
|
-
data: `<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName="${config.applicationName}" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009"><Actions><ObjectPath Id="46" ObjectPathId="45" /><Method Name="GetSPOContainerTypes" Id="47" ObjectPathId="45"><Parameters><Parameter Type="Enum">1</Parameter></Parameters></Method></Actions><ObjectPaths><Constructor Id="45" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" /></ObjectPaths></Request>`
|
|
64
|
-
};
|
|
65
|
-
const res = await request.post(requestOptions);
|
|
66
|
-
const json = JSON.parse(res);
|
|
67
|
-
const response = json[0];
|
|
68
|
-
if (response.ErrorInfo) {
|
|
69
|
-
throw new Error(response.ErrorInfo.ErrorMessage);
|
|
70
|
-
}
|
|
71
|
-
const containerTypes = json[json.length - 1];
|
|
72
|
-
return containerTypes;
|
|
73
|
-
},
|
|
74
56
|
async waitUntilFinished({ operationId, siteUrl, logger, currentContext, debug, verbose }) {
|
|
75
57
|
const resFormDigest = await spo.ensureFormDigest(siteUrl, logger, currentContext, debug);
|
|
76
58
|
currentContext = resFormDigest;
|
package/dist/utils/spp.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import request from '../request.js';
|
|
2
|
+
import { formatting } from './formatting.js';
|
|
2
3
|
export const spp = {
|
|
3
4
|
/**
|
|
4
5
|
* Asserts whether the specified site is a content center
|
|
5
6
|
* @param siteUrl The URL of the site to check
|
|
7
|
+
* @param logger Logger instance
|
|
8
|
+
* @param verbose Whether to log verbose messages
|
|
6
9
|
* @throws error when site is not a content center.
|
|
7
10
|
*/
|
|
8
|
-
async assertSiteIsContentCenter(siteUrl) {
|
|
11
|
+
async assertSiteIsContentCenter(siteUrl, logger, verbose) {
|
|
12
|
+
if (verbose) {
|
|
13
|
+
await logger.log(`Checking if '${siteUrl}' is a valid content center site...`);
|
|
14
|
+
}
|
|
9
15
|
const requestOptions = {
|
|
10
16
|
url: `${siteUrl}/_api/web?$select=WebTemplateConfiguration`,
|
|
11
17
|
headers: {
|
|
@@ -17,6 +23,58 @@ export const spp = {
|
|
|
17
23
|
if (response.WebTemplateConfiguration !== 'CONTENTCTR#0') {
|
|
18
24
|
throw Error(`${siteUrl} is not a content site.`);
|
|
19
25
|
}
|
|
26
|
+
},
|
|
27
|
+
/**
|
|
28
|
+
* Gets a SharePoint Premium model by title
|
|
29
|
+
* @param contentCenterUrl a content center site URL
|
|
30
|
+
* @param title model title
|
|
31
|
+
* @param logger Logger instance
|
|
32
|
+
* @param verbose Whether to log verbose messages
|
|
33
|
+
* @returns SharePoint Premium model
|
|
34
|
+
*/
|
|
35
|
+
async getModelByTitle(contentCenterUrl, title, logger, verbose) {
|
|
36
|
+
if (verbose) {
|
|
37
|
+
await logger.log(`Retrieving model information...`);
|
|
38
|
+
}
|
|
39
|
+
let requestTitle = title.toLowerCase();
|
|
40
|
+
if (!requestTitle.endsWith('.classifier')) {
|
|
41
|
+
requestTitle += '.classifier';
|
|
42
|
+
}
|
|
43
|
+
const requestUrl = `${contentCenterUrl}/_api/machinelearning/models/getbytitle('${formatting.encodeQueryParameter(requestTitle)}')`;
|
|
44
|
+
const requestOptions = {
|
|
45
|
+
url: requestUrl,
|
|
46
|
+
headers: {
|
|
47
|
+
accept: 'application/json;odata=nometadata'
|
|
48
|
+
},
|
|
49
|
+
responseType: 'json'
|
|
50
|
+
};
|
|
51
|
+
const result = await request.get(requestOptions);
|
|
52
|
+
if (result['odata.null'] === true) {
|
|
53
|
+
throw Error(`Model '${title}' was not found.`);
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
},
|
|
57
|
+
/**
|
|
58
|
+
* Gets a SharePoint Premium model by unique id
|
|
59
|
+
* @param contentCenterUrl a content center site URL
|
|
60
|
+
* @param id model unique id
|
|
61
|
+
* @param logger Logger instance
|
|
62
|
+
* @param verbose Whether to log verbose messages
|
|
63
|
+
* @returns SharePoint Premium model
|
|
64
|
+
*/
|
|
65
|
+
async getModelById(contentCenterUrl, id, logger, verbose) {
|
|
66
|
+
if (verbose) {
|
|
67
|
+
await logger.log(`Retrieving model information...`);
|
|
68
|
+
}
|
|
69
|
+
const requestUrl = `${contentCenterUrl}/_api/machinelearning/models/getbyuniqueid('${id}')`;
|
|
70
|
+
const requestOptions = {
|
|
71
|
+
url: requestUrl,
|
|
72
|
+
headers: {
|
|
73
|
+
accept: 'application/json;odata=nometadata'
|
|
74
|
+
},
|
|
75
|
+
responseType: 'json'
|
|
76
|
+
};
|
|
77
|
+
return await request.get(requestOptions);
|
|
20
78
|
}
|
|
21
79
|
};
|
|
22
80
|
//# sourceMappingURL=spp.js.map
|
package/dist/utils/zod.js
CHANGED
|
@@ -110,16 +110,41 @@ function parseDef(def, options, currentOption) {
|
|
|
110
110
|
}
|
|
111
111
|
} while (parsedDef);
|
|
112
112
|
}
|
|
113
|
+
function optionToString(optionInfo) {
|
|
114
|
+
let s = '';
|
|
115
|
+
if (optionInfo.short) {
|
|
116
|
+
s += `-${optionInfo.short}, `;
|
|
117
|
+
}
|
|
118
|
+
s += `--${optionInfo.long}`;
|
|
119
|
+
if (optionInfo.type !== 'boolean') {
|
|
120
|
+
s += ' ';
|
|
121
|
+
s += optionInfo.required ? '<' : '[';
|
|
122
|
+
s += optionInfo.long;
|
|
123
|
+
s += optionInfo.required ? '>' : ']';
|
|
124
|
+
}
|
|
125
|
+
return s;
|
|
126
|
+
}
|
|
127
|
+
;
|
|
113
128
|
export const zod = {
|
|
114
129
|
alias(alias, type) {
|
|
115
130
|
type._def.alias = alias;
|
|
116
131
|
return type;
|
|
117
132
|
},
|
|
118
|
-
|
|
133
|
+
schemaToOptionInfo(schema) {
|
|
119
134
|
const options = [];
|
|
120
135
|
parseDef(schema._def, options);
|
|
121
136
|
return options;
|
|
122
137
|
},
|
|
138
|
+
schemaToOptions(schema) {
|
|
139
|
+
const optionsInfo = this.schemaToOptionInfo(schema);
|
|
140
|
+
const options = optionsInfo.map(option => {
|
|
141
|
+
return {
|
|
142
|
+
option: optionToString(option),
|
|
143
|
+
autocomplete: option.autocomplete
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
return options;
|
|
147
|
+
},
|
|
123
148
|
coercedEnum: (e) => z.preprocess(val => {
|
|
124
149
|
const target = String(val)?.toLowerCase();
|
|
125
150
|
for (const k of Object.values(e)) {
|
|
@@ -17,7 +17,7 @@ m365 adaptivecard send [options]
|
|
|
17
17
|
: URL where to send the card to.
|
|
18
18
|
|
|
19
19
|
`-t, --title [title]`
|
|
20
|
-
: Title of the card.
|
|
20
|
+
: Title of the card. If you specify `title` and `card`, the `title` will be merged into the card.
|
|
21
21
|
|
|
22
22
|
`-d, --description [description]`
|
|
23
23
|
: Contents of the card.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import Global from '/docs/cmd/_global.mdx';
|
|
2
|
+
import Tabs from '@theme/Tabs';
|
|
3
|
+
import TabItem from '@theme/TabItem';
|
|
4
|
+
|
|
5
|
+
# cli app reconsent
|
|
6
|
+
|
|
7
|
+
Reconsent all permission scopes used in CLI for Microsoft 365
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
m365 cli app reconsent [options]
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Options
|
|
16
|
+
|
|
17
|
+
<Global />
|
|
18
|
+
|
|
19
|
+
## Remarks
|
|
20
|
+
|
|
21
|
+
This command will add all missing scopes used in CLI for Microsoft 365 to your current app registration. It will only add missing scopes and won't remove any scopes that are already present in the app registration.
|
|
22
|
+
|
|
23
|
+
## Examples
|
|
24
|
+
|
|
25
|
+
Consent all permission scopes used in CLI for Microsoft 365 to the current app registration
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
m365 cli app reconsent
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Response
|
|
32
|
+
|
|
33
|
+
<Tabs>
|
|
34
|
+
<TabItem value="JSON">
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
"To consent to the new scopes for your Microsoft Entra application registration, please navigate to the following URL: https://login.microsoftonline.com/f72203fd-b0a0-472d-85eb-079a117a80de/adminconsent?client_id=62b981af-59d3-4d25-8baf-6cc067a03102"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
</TabItem>
|
|
41
|
+
<TabItem value="Text">
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
To consent to the new scopes for your Microsoft Entra application registration, please navigate to the following URL: https://login.microsoftonline.com/f72203fd-b0a0-472d-85eb-079a117a80de/adminconsent?client_id=62b981af-59d3-4d25-8baf-6cc067a03102
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
</TabItem>
|
|
48
|
+
<TabItem value="CSV">
|
|
49
|
+
|
|
50
|
+
```csv
|
|
51
|
+
To consent to the new scopes for your Microsoft Entra application registration, please navigate to the following URL: https://login.microsoftonline.com/f72203fd-b0a0-472d-85eb-079a117a80de/adminconsent?client_id=62b981af-59d3-4d25-8baf-6cc067a03102
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
</TabItem>
|
|
55
|
+
<TabItem value="Markdown">
|
|
56
|
+
|
|
57
|
+
```md
|
|
58
|
+
To consent to the new scopes for your Microsoft Entra application registration, please navigate to the following URL: https://login.microsoftonline.com/f72203fd-b0a0-472d-85eb-079a117a80de/adminconsent?client_id=62b981af-59d3-4d25-8baf-6cc067a03102
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
</TabItem>
|
|
62
|
+
</Tabs>
|
|
63
|
+
|