From b60eb29c169c3dc69b11b940a4224bd6a03e479c Mon Sep 17 00:00:00 2001 From: Peter Ombwa Date: Mon, 22 Jun 2020 17:55:47 -0700 Subject: [PATCH 1/7] Add GraphPSCmdlet base class --- .../Users.Calendar/custom/GraphPSCmdlet.cs | 17 ++- .../Users.Calendar/custom/Module.cs | 12 +- src/readme.graph.md | 23 ++- tools/Custom/GraphPSCmdlet.cs | 131 ++++++++++++++++++ 4 files changed, 167 insertions(+), 16 deletions(-) rename tools/Custom/ListCmdlet.cs => src/Beta/Users.Calendar/Users.Calendar/custom/GraphPSCmdlet.cs (87%) create mode 100644 tools/Custom/GraphPSCmdlet.cs diff --git a/tools/Custom/ListCmdlet.cs b/src/Beta/Users.Calendar/Users.Calendar/custom/GraphPSCmdlet.cs similarity index 87% rename from tools/Custom/ListCmdlet.cs rename to src/Beta/Users.Calendar/Users.Calendar/custom/GraphPSCmdlet.cs index 2fd7cdd448c..58d8b0c532e 100644 --- a/tools/Custom/ListCmdlet.cs +++ b/src/Beta/Users.Calendar/Users.Calendar/custom/GraphPSCmdlet.cs @@ -1,10 +1,11 @@ + // ------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. // ------------------------------------------------------------------------------ namespace Microsoft.Graph.PowerShell.Cmdlets.Custom { - - public partial class ListCmdlet : global::System.Management.Automation.PSCmdlet + using static Microsoft.Graph.PowerShell.Runtime.Extensions; + public partial class GraphPSCmdlet : global::System.Management.Automation.PSCmdlet { /// Backing field for property. private global::System.Management.Automation.SwitchParameter _all; @@ -114,5 +115,17 @@ public bool ShouldIteratePages(global::System.Collections.Generic.Dictionary response, ref global::System.Threading.Tasks.Task returnNow) + { + if (responseMessage.IsSuccessStatusCode) + { + if (MyInvocation?.BoundParameters?.ContainsKey("PassThru") == true) + { + WriteObject(true); + } + returnNow = global::System.Threading.Tasks.Task.FromResult(true); + } + } } } \ No newline at end of file diff --git a/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs b/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs index d048630b695..4a0e0f6ebcc 100644 --- a/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs +++ b/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs @@ -15,17 +15,7 @@ public partial class Module { partial void BeforeCreatePipeline(System.Management.Automation.InvocationInfo invocationInfo, ref Runtime.HttpPipeline pipeline) { - using (var powershell = PowerShell.Create(RunspaceMode.CurrentRunspace)) - { - powershell.Commands.AddCommand(new Command($"$executioncontext.SessionState.PSVariable.GetValue('{Constants.GraphAuthConfigId}')", true)); - - AuthConfig authConfig = powershell.Invoke().FirstOrDefault(); - - if (authConfig == null) - throw new Exception("Authentication needed, call Connect-Graph."); - - pipeline = new Runtime.HttpPipeline(new Runtime.HttpClientFactory(HttpHelpers.GetGraphHttpClient(authConfig))); - } + pipeline = new Runtime.HttpPipeline(new Runtime.HttpClientFactory(HttpHelpers.GetGraphHttpClient())); } } } diff --git a/src/readme.graph.md b/src/readme.graph.md index f8893b802a4..197f849780c 100644 --- a/src/readme.graph.md +++ b/src/readme.graph.md @@ -380,19 +380,36 @@ directive: } return $; } +# Add GraphPSCmdlet base class. +# - Override OnDefault to handle all success, 2xx response, as success and not error. + - from: source-file-csharp + where: $ + transform: > + if (!$documentPath.match(/generated%2Fcmdlets%2F\w*.cs/gm)) + { + return $; + } else { + let psBaseClassImplementationRegex = /(\s*:\s*)(global::System.Management.Automation.PSCmdlet)/gmi + $ = $.replace(psBaseClassImplementationRegex, '$1Microsoft.Graph.PowerShell.Cmdlets.Custom.GraphPSCmdlet'); + + let overrideOnDefaultRegex = /(\s*)(partial\s*void\s*overrideOnDefault)/gmi + let overrideOnDefaultImplementation = "$1partial void overrideOnDefault(global::System.Net.Http.HttpResponseMessage responseMessage, global::System.Threading.Tasks.Task response, ref global::System.Threading.Tasks.Task returnNow) => this.OverrideCmdletOnDefault(responseMessage, response,ref returnNow);$1$2" + $ = $.replace(overrideOnDefaultRegex, overrideOnDefaultImplementation); + + return $; + } + # Add custom -All parameter to *_List cmdlets that support Odata next link. - from: source-file-csharp where: $ transform: > - if (!$documentPath.match(/generated%2Fcmdlets%2FGet\w*_List.cs/gm)) + if (!$documentPath.match(/generated%2Fcmdlets%2FGet\w*_List\d*.cs/gm)) { return $; } else { let odataNextLinkRegex = /(^\s*)(if\s*\(\s*result.OdataNextLink\s*!=\s*null\s*\))/gmi if($.match(odataNextLinkRegex)) { $ = $.replace(odataNextLinkRegex, '$1if (result.OdataNextLink != null && this.ShouldIteratePages(this.InvocationInformation.BoundParameters, result.Value.Length))\n$1'); - let psBaseClassImplementationRegex = /(\s*:\s*)(global::System.Management.Automation.PSCmdlet)/gmi - $ = $.replace(psBaseClassImplementationRegex, '$1Microsoft.Graph.PowerShell.Cmdlets.Custom.ListCmdlet'); let beginProcessingRegex = /(^\s*)(protected\s*override\s*void\s*BeginProcessing\(\)\s*{)/gmi $ = $.replace(beginProcessingRegex, '$1$2\n$1$1if (this.InvocationInformation.BoundParameters.ContainsKey("PageSize")){ InitializePaging(ref this.__invocationInfo, ref this._pageSize); }\n$1'); diff --git a/tools/Custom/GraphPSCmdlet.cs b/tools/Custom/GraphPSCmdlet.cs new file mode 100644 index 00000000000..58d8b0c532e --- /dev/null +++ b/tools/Custom/GraphPSCmdlet.cs @@ -0,0 +1,131 @@ + +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +// ------------------------------------------------------------------------------ +namespace Microsoft.Graph.PowerShell.Cmdlets.Custom +{ + using static Microsoft.Graph.PowerShell.Runtime.Extensions; + public partial class GraphPSCmdlet : global::System.Management.Automation.PSCmdlet + { + /// Backing field for property. + private global::System.Management.Automation.SwitchParameter _all; + + /// List All pages + [global::System.Management.Automation.Parameter(Mandatory = false, HelpMessage = "List all pages")] + [Microsoft.Graph.PowerShell.Runtime.Info( + Required = false, + ReadOnly = false, + Description = @"List all pages", + SerializedName = @"$all", + PossibleTypes = new[] { typeof(global::System.Management.Automation.SwitchParameter) })] + [global::Microsoft.Graph.PowerShell.Category(global::Microsoft.Graph.PowerShell.ParameterCategory.Runtime)] + public global::System.Management.Automation.SwitchParameter All { get => this._all; set => this._all = value; } + + /// + /// Default number of items per page. + /// + internal const int DefaultPageSize = 100; + + /// + /// Maximum number of items per page. + /// + internal const int MaxPageSize = 999; + + /// + /// Original page size/top/limit passed to Cmdlet via parameter. + /// + internal int originalPageSize = 0; + + /// + /// Total number of pages required to iterate page collections excluding overflow items. + /// + internal int requiredPages = 0; + + /// + /// A count of iterated pages thus far. + /// + internal int iteratedPages = 0; + + /// + /// Total number of overflow items, less than the maximum number of items in a page. + /// Modulus of original page size. + /// + internal int overflowItemsCount = 0; + + /// + /// Total number of fetched items. + /// + internal int totalFetchedItems = 0; + + /// + /// Initializes paging values. + /// + /// A reference to object. + /// A reference to page size parameter. + public void InitializePaging(ref global::System.Management.Automation.InvocationInfo invocationInfo, ref int PageSize) + { + if (PageSize > MaxPageSize) + { + invocationInfo.BoundParameters["All"] = true; + originalPageSize = PageSize; + requiredPages = PageSize / DefaultPageSize; + overflowItemsCount = PageSize % DefaultPageSize; + invocationInfo.BoundParameters["PageSize"] = DefaultPageSize; + PageSize = DefaultPageSize; + } + } + + /// + /// Determines whether the cmdlet should follow the OData next link url. + /// + /// The bound parameters of the cmdlet. + /// Current page items count. + /// True if it can iterate pages; False if it can't. + public bool ShouldIteratePages(global::System.Collections.Generic.Dictionary boundParameters, int itemsCount) + { + iteratedPages++; + totalFetchedItems += itemsCount; + if ((boundParameters.ContainsKey("All") && !boundParameters.ContainsKey("PageSize")) || + (boundParameters.ContainsKey("PageSize") && totalFetchedItems < originalPageSize)) + return true; + else + return false; + } + + /// + /// Gets an OData next link for the overflow items. + /// + /// The OData next link returned by the service. + /// An OData next link URI for the overflow items. + public global::System.Uri GetOverflowItemsNextLinkUri(global::System.Uri requestUri) + { + var nextLinkUri = new global::System.UriBuilder(requestUri); + if (requiredPages == iteratedPages && overflowItemsCount > 0) + { + if (nextLinkUri.Query.Contains("$top")) + { + global::System.Collections.Specialized.NameValueCollection queryString = global::System.Web.HttpUtility.ParseQueryString(nextLinkUri.Query); + queryString["$top"] = global::System.Uri.EscapeDataString(overflowItemsCount.ToString()); + nextLinkUri.Query = queryString.ToString(); + } + else + { + nextLinkUri.Query += $"$top=" + global::System.Uri.EscapeDataString(overflowItemsCount.ToString()); + } + } + return nextLinkUri.Uri; + } + + public void OverrideCmdletOnDefault(global::System.Net.Http.HttpResponseMessage responseMessage, global::System.Threading.Tasks.Task response, ref global::System.Threading.Tasks.Task returnNow) + { + if (responseMessage.IsSuccessStatusCode) + { + if (MyInvocation?.BoundParameters?.ContainsKey("PassThru") == true) + { + WriteObject(true); + } + returnNow = global::System.Threading.Tasks.Task.FromResult(true); + } + } + } +} \ No newline at end of file From c8da2ccebb87cbda3d1fa138cfa9e94967b7f9d7 Mon Sep 17 00:00:00 2001 From: Peter Ombwa Date: Tue, 23 Jun 2020 10:56:11 -0700 Subject: [PATCH 2/7] Move OverrideOnDefault to PSCmdletExtensions --- .../Extensions/PSCmdletExtensions.cs | 28 +++++++++++++++++++ .../{GraphPSCmdlet.cs => ListCmdlet.cs} | 17 ++--------- src/readme.graph.md | 8 +++--- .../{GraphPSCmdlet.cs => ListCmdlet.cs} | 17 ++--------- 4 files changed, 36 insertions(+), 34 deletions(-) create mode 100644 src/Authentication/Authentication/Extensions/PSCmdletExtensions.cs rename src/Beta/Users.Calendar/Users.Calendar/custom/{GraphPSCmdlet.cs => ListCmdlet.cs} (87%) rename tools/Custom/{GraphPSCmdlet.cs => ListCmdlet.cs} (87%) diff --git a/src/Authentication/Authentication/Extensions/PSCmdletExtensions.cs b/src/Authentication/Authentication/Extensions/PSCmdletExtensions.cs new file mode 100644 index 00000000000..d882e83d57f --- /dev/null +++ b/src/Authentication/Authentication/Extensions/PSCmdletExtensions.cs @@ -0,0 +1,28 @@ +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. +// ------------------------------------------------------------------------------ + +namespace Microsoft.Graph.PowerShell +{ + using System.Management.Automation; + public static class PSCmdletExtensions + { + /// + /// Overrides OnDefault method in the generated cmdlets. + /// + /// The calling + /// The HTTP response message from the service. + /// Determines whether the caller should return after OverrideOnDefault is called, or not. + public static void OverrideOnDefault(this PSCmdlet cmdlet, global::System.Net.Http.HttpResponseMessage responseMessage, ref global::System.Threading.Tasks.Task returnNow) + { + if (responseMessage.IsSuccessStatusCode) + { + if (cmdlet.MyInvocation?.BoundParameters?.ContainsKey("PassThru") == true) + { + cmdlet.WriteObject(true); + } + returnNow = global::System.Threading.Tasks.Task.FromResult(true); + } + } + } +} diff --git a/src/Beta/Users.Calendar/Users.Calendar/custom/GraphPSCmdlet.cs b/src/Beta/Users.Calendar/Users.Calendar/custom/ListCmdlet.cs similarity index 87% rename from src/Beta/Users.Calendar/Users.Calendar/custom/GraphPSCmdlet.cs rename to src/Beta/Users.Calendar/Users.Calendar/custom/ListCmdlet.cs index 58d8b0c532e..2fd7cdd448c 100644 --- a/src/Beta/Users.Calendar/Users.Calendar/custom/GraphPSCmdlet.cs +++ b/src/Beta/Users.Calendar/Users.Calendar/custom/ListCmdlet.cs @@ -1,11 +1,10 @@ - // ------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. // ------------------------------------------------------------------------------ namespace Microsoft.Graph.PowerShell.Cmdlets.Custom { - using static Microsoft.Graph.PowerShell.Runtime.Extensions; - public partial class GraphPSCmdlet : global::System.Management.Automation.PSCmdlet + + public partial class ListCmdlet : global::System.Management.Automation.PSCmdlet { /// Backing field for property. private global::System.Management.Automation.SwitchParameter _all; @@ -115,17 +114,5 @@ public bool ShouldIteratePages(global::System.Collections.Generic.Dictionary response, ref global::System.Threading.Tasks.Task returnNow) - { - if (responseMessage.IsSuccessStatusCode) - { - if (MyInvocation?.BoundParameters?.ContainsKey("PassThru") == true) - { - WriteObject(true); - } - returnNow = global::System.Threading.Tasks.Task.FromResult(true); - } - } } } \ No newline at end of file diff --git a/src/readme.graph.md b/src/readme.graph.md index 197f849780c..761c4bc3bdc 100644 --- a/src/readme.graph.md +++ b/src/readme.graph.md @@ -389,11 +389,8 @@ directive: { return $; } else { - let psBaseClassImplementationRegex = /(\s*:\s*)(global::System.Management.Automation.PSCmdlet)/gmi - $ = $.replace(psBaseClassImplementationRegex, '$1Microsoft.Graph.PowerShell.Cmdlets.Custom.GraphPSCmdlet'); - let overrideOnDefaultRegex = /(\s*)(partial\s*void\s*overrideOnDefault)/gmi - let overrideOnDefaultImplementation = "$1partial void overrideOnDefault(global::System.Net.Http.HttpResponseMessage responseMessage, global::System.Threading.Tasks.Task response, ref global::System.Threading.Tasks.Task returnNow) => this.OverrideCmdletOnDefault(responseMessage, response,ref returnNow);$1$2" + let overrideOnDefaultImplementation = "$1partial void overrideOnDefault(global::System.Net.Http.HttpResponseMessage responseMessage, global::System.Threading.Tasks.Task response, ref global::System.Threading.Tasks.Task returnNow) => this.OverrideOnDefault(responseMessage,ref returnNow);$1$2" $ = $.replace(overrideOnDefaultRegex, overrideOnDefaultImplementation); return $; @@ -411,6 +408,9 @@ directive: if($.match(odataNextLinkRegex)) { $ = $.replace(odataNextLinkRegex, '$1if (result.OdataNextLink != null && this.ShouldIteratePages(this.InvocationInformation.BoundParameters, result.Value.Length))\n$1'); + let psBaseClassImplementationRegex = /(\s*:\s*)(global::System.Management.Automation.PSCmdlet)/gmi + $ = $.replace(psBaseClassImplementationRegex, '$1Microsoft.Graph.PowerShell.Cmdlets.Custom.ListCmdlet'); + let beginProcessingRegex = /(^\s*)(protected\s*override\s*void\s*BeginProcessing\(\)\s*{)/gmi $ = $.replace(beginProcessingRegex, '$1$2\n$1$1if (this.InvocationInformation.BoundParameters.ContainsKey("PageSize")){ InitializePaging(ref this.__invocationInfo, ref this._pageSize); }\n$1'); diff --git a/tools/Custom/GraphPSCmdlet.cs b/tools/Custom/ListCmdlet.cs similarity index 87% rename from tools/Custom/GraphPSCmdlet.cs rename to tools/Custom/ListCmdlet.cs index 58d8b0c532e..2fd7cdd448c 100644 --- a/tools/Custom/GraphPSCmdlet.cs +++ b/tools/Custom/ListCmdlet.cs @@ -1,11 +1,10 @@ - // ------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. // ------------------------------------------------------------------------------ namespace Microsoft.Graph.PowerShell.Cmdlets.Custom { - using static Microsoft.Graph.PowerShell.Runtime.Extensions; - public partial class GraphPSCmdlet : global::System.Management.Automation.PSCmdlet + + public partial class ListCmdlet : global::System.Management.Automation.PSCmdlet { /// Backing field for property. private global::System.Management.Automation.SwitchParameter _all; @@ -115,17 +114,5 @@ public bool ShouldIteratePages(global::System.Collections.Generic.Dictionary response, ref global::System.Threading.Tasks.Task returnNow) - { - if (responseMessage.IsSuccessStatusCode) - { - if (MyInvocation?.BoundParameters?.ContainsKey("PassThru") == true) - { - WriteObject(true); - } - returnNow = global::System.Threading.Tasks.Task.FromResult(true); - } - } } } \ No newline at end of file From ff09f4266abe1d29ed0f24a66ee5b1d39a843a85 Mon Sep 17 00:00:00 2001 From: Peter Ombwa Date: Tue, 23 Jun 2020 14:17:58 -0700 Subject: [PATCH 3/7] Allow customers to specify -PageSize with -All --- .../Users.Calendar/custom/ListCmdlet.cs | 118 ------------------ .../Users.Calendar/custom/Module.cs | 12 +- tools/Custom/ListCmdlet.cs | 8 +- 3 files changed, 17 insertions(+), 121 deletions(-) delete mode 100644 src/Beta/Users.Calendar/Users.Calendar/custom/ListCmdlet.cs diff --git a/src/Beta/Users.Calendar/Users.Calendar/custom/ListCmdlet.cs b/src/Beta/Users.Calendar/Users.Calendar/custom/ListCmdlet.cs deleted file mode 100644 index 2fd7cdd448c..00000000000 --- a/src/Beta/Users.Calendar/Users.Calendar/custom/ListCmdlet.cs +++ /dev/null @@ -1,118 +0,0 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. -// ------------------------------------------------------------------------------ -namespace Microsoft.Graph.PowerShell.Cmdlets.Custom -{ - - public partial class ListCmdlet : global::System.Management.Automation.PSCmdlet - { - /// Backing field for property. - private global::System.Management.Automation.SwitchParameter _all; - - /// List All pages - [global::System.Management.Automation.Parameter(Mandatory = false, HelpMessage = "List all pages")] - [Microsoft.Graph.PowerShell.Runtime.Info( - Required = false, - ReadOnly = false, - Description = @"List all pages", - SerializedName = @"$all", - PossibleTypes = new[] { typeof(global::System.Management.Automation.SwitchParameter) })] - [global::Microsoft.Graph.PowerShell.Category(global::Microsoft.Graph.PowerShell.ParameterCategory.Runtime)] - public global::System.Management.Automation.SwitchParameter All { get => this._all; set => this._all = value; } - - /// - /// Default number of items per page. - /// - internal const int DefaultPageSize = 100; - - /// - /// Maximum number of items per page. - /// - internal const int MaxPageSize = 999; - - /// - /// Original page size/top/limit passed to Cmdlet via parameter. - /// - internal int originalPageSize = 0; - - /// - /// Total number of pages required to iterate page collections excluding overflow items. - /// - internal int requiredPages = 0; - - /// - /// A count of iterated pages thus far. - /// - internal int iteratedPages = 0; - - /// - /// Total number of overflow items, less than the maximum number of items in a page. - /// Modulus of original page size. - /// - internal int overflowItemsCount = 0; - - /// - /// Total number of fetched items. - /// - internal int totalFetchedItems = 0; - - /// - /// Initializes paging values. - /// - /// A reference to object. - /// A reference to page size parameter. - public void InitializePaging(ref global::System.Management.Automation.InvocationInfo invocationInfo, ref int PageSize) - { - if (PageSize > MaxPageSize) - { - invocationInfo.BoundParameters["All"] = true; - originalPageSize = PageSize; - requiredPages = PageSize / DefaultPageSize; - overflowItemsCount = PageSize % DefaultPageSize; - invocationInfo.BoundParameters["PageSize"] = DefaultPageSize; - PageSize = DefaultPageSize; - } - } - - /// - /// Determines whether the cmdlet should follow the OData next link url. - /// - /// The bound parameters of the cmdlet. - /// Current page items count. - /// True if it can iterate pages; False if it can't. - public bool ShouldIteratePages(global::System.Collections.Generic.Dictionary boundParameters, int itemsCount) - { - iteratedPages++; - totalFetchedItems += itemsCount; - if ((boundParameters.ContainsKey("All") && !boundParameters.ContainsKey("PageSize")) || - (boundParameters.ContainsKey("PageSize") && totalFetchedItems < originalPageSize)) - return true; - else - return false; - } - - /// - /// Gets an OData next link for the overflow items. - /// - /// The OData next link returned by the service. - /// An OData next link URI for the overflow items. - public global::System.Uri GetOverflowItemsNextLinkUri(global::System.Uri requestUri) - { - var nextLinkUri = new global::System.UriBuilder(requestUri); - if (requiredPages == iteratedPages && overflowItemsCount > 0) - { - if (nextLinkUri.Query.Contains("$top")) - { - global::System.Collections.Specialized.NameValueCollection queryString = global::System.Web.HttpUtility.ParseQueryString(nextLinkUri.Query); - queryString["$top"] = global::System.Uri.EscapeDataString(overflowItemsCount.ToString()); - nextLinkUri.Query = queryString.ToString(); - } - else - { - nextLinkUri.Query += $"$top=" + global::System.Uri.EscapeDataString(overflowItemsCount.ToString()); - } - } - return nextLinkUri.Uri; - } - } -} \ No newline at end of file diff --git a/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs b/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs index 4a0e0f6ebcc..873f4b2faf7 100644 --- a/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs +++ b/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs @@ -15,7 +15,17 @@ public partial class Module { partial void BeforeCreatePipeline(System.Management.Automation.InvocationInfo invocationInfo, ref Runtime.HttpPipeline pipeline) { - pipeline = new Runtime.HttpPipeline(new Runtime.HttpClientFactory(HttpHelpers.GetGraphHttpClient())); + using (var powershell = PowerShell.Create(RunspaceMode.CurrentRunspace)) + { + powershell.Commands.AddCommand(new Command($"$executioncontext.SessionState.PSVariable.GetValue('{Constants.GraphAuthConfigId}')", true)); + + AuthConfig authConfig = powershell.Invoke().FirstOrDefault(); + + if (authConfig == null) + throw new Exception("Authentication needed, call Connect-Graph."); + + pipeline = new Runtime.HttpPipeline(new Runtime.HttpClientFactory(HttpHelpers.GetGraphHttpClient(authConfig))); + } } } } diff --git a/tools/Custom/ListCmdlet.cs b/tools/Custom/ListCmdlet.cs index 2fd7cdd448c..e57050bf8e5 100644 --- a/tools/Custom/ListCmdlet.cs +++ b/tools/Custom/ListCmdlet.cs @@ -84,11 +84,15 @@ public bool ShouldIteratePages(global::System.Collections.Generic.Dictionary From 77a717b92dbe2bb2e190ba71e2f6dcbbaefb8212 Mon Sep 17 00:00:00 2001 From: Peter Ombwa Date: Tue, 23 Jun 2020 14:22:32 -0700 Subject: [PATCH 4/7] Remove spaces. --- .../Users.Calendar/Users.Calendar/custom/Module.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs b/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs index 873f4b2faf7..d048630b695 100644 --- a/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs +++ b/src/Beta/Users.Calendar/Users.Calendar/custom/Module.cs @@ -16,15 +16,15 @@ public partial class Module partial void BeforeCreatePipeline(System.Management.Automation.InvocationInfo invocationInfo, ref Runtime.HttpPipeline pipeline) { using (var powershell = PowerShell.Create(RunspaceMode.CurrentRunspace)) - { - powershell.Commands.AddCommand(new Command($"$executioncontext.SessionState.PSVariable.GetValue('{Constants.GraphAuthConfigId}')", true)); + { + powershell.Commands.AddCommand(new Command($"$executioncontext.SessionState.PSVariable.GetValue('{Constants.GraphAuthConfigId}')", true)); - AuthConfig authConfig = powershell.Invoke().FirstOrDefault(); + AuthConfig authConfig = powershell.Invoke().FirstOrDefault(); - if (authConfig == null) - throw new Exception("Authentication needed, call Connect-Graph."); + if (authConfig == null) + throw new Exception("Authentication needed, call Connect-Graph."); - pipeline = new Runtime.HttpPipeline(new Runtime.HttpClientFactory(HttpHelpers.GetGraphHttpClient(authConfig))); + pipeline = new Runtime.HttpPipeline(new Runtime.HttpClientFactory(HttpHelpers.GetGraphHttpClient(authConfig))); } } } From 6c01e5d745b23f899f9d56f5fa128cdae1c8ece4 Mon Sep 17 00:00:00 2001 From: Peter Ombwa Date: Tue, 23 Jun 2020 14:26:11 -0700 Subject: [PATCH 5/7] Update readme.graph.md --- src/readme.graph.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/readme.graph.md b/src/readme.graph.md index 761c4bc3bdc..c871c081bfd 100644 --- a/src/readme.graph.md +++ b/src/readme.graph.md @@ -380,8 +380,7 @@ directive: } return $; } -# Add GraphPSCmdlet base class. -# - Override OnDefault to handle all success, 2xx response, as success and not error. +# Override OnDefault to handle all success, 2xx responses, as success and not error. - from: source-file-csharp where: $ transform: > From aef652433bfb0212e6f8dc74787aada8eb6ca46d Mon Sep 17 00:00:00 2001 From: Peter Ombwa Date: Mon, 29 Jun 2020 11:25:52 -0700 Subject: [PATCH 6/7] Add -PageSize parameter. --- src/readme.graph.md | 6 ++-- tools/Custom/ListCmdlet.cs | 74 +++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/src/readme.graph.md b/src/readme.graph.md index c871c081bfd..08955df8cb4 100644 --- a/src/readme.graph.md +++ b/src/readme.graph.md @@ -80,9 +80,7 @@ directive: - where: parameter-name: Top set: - parameter-name: PageSize alias: - - Top - Limit - where: parameter-name: Select @@ -395,7 +393,7 @@ directive: return $; } -# Add custom -All parameter to *_List cmdlets that support Odata next link. +# Add custom -PageSize parameter to *_List cmdlets that support Odata next link. - from: source-file-csharp where: $ transform: > @@ -411,7 +409,7 @@ directive: $ = $.replace(psBaseClassImplementationRegex, '$1Microsoft.Graph.PowerShell.Cmdlets.Custom.ListCmdlet'); let beginProcessingRegex = /(^\s*)(protected\s*override\s*void\s*BeginProcessing\(\)\s*{)/gmi - $ = $.replace(beginProcessingRegex, '$1$2\n$1$1if (this.InvocationInformation.BoundParameters.ContainsKey("PageSize")){ InitializePaging(ref this.__invocationInfo, ref this._pageSize); }\n$1'); + $ = $.replace(beginProcessingRegex, '$1$2\n$1 if (this.InvocationInformation?.BoundParameters != null){ InitializePaging(ref this.__invocationInfo, ref this._top); }\n$1'); let odataNextLinkCallRegex = /(^\s*)(await\s*this\.Client\.UsersUserListUser_Call\(requestMessage\,\s*onOk\,\s*onDefault\,\s*this\,\s*Pipeline\)\;)/gmi $ = $.replace(odataNextLinkCallRegex, '$1requestMessage.RequestUri = GetOverflowItemsNextLinkUri(requestMessage.RequestUri);\n$1$2'); diff --git a/tools/Custom/ListCmdlet.cs b/tools/Custom/ListCmdlet.cs index e57050bf8e5..051ddcdde57 100644 --- a/tools/Custom/ListCmdlet.cs +++ b/tools/Custom/ListCmdlet.cs @@ -3,22 +3,23 @@ // ------------------------------------------------------------------------------ namespace Microsoft.Graph.PowerShell.Cmdlets.Custom { + using System; + using System.Management.Automation; public partial class ListCmdlet : global::System.Management.Automation.PSCmdlet { - /// Backing field for property. - private global::System.Management.Automation.SwitchParameter _all; - - /// List All pages - [global::System.Management.Automation.Parameter(Mandatory = false, HelpMessage = "List all pages")] + /// Backing field for property. + private int _pageSize; + + /// Sets the page size of results. + [global::System.Management.Automation.Parameter(Mandatory = false, HelpMessage = "Sets the page size of results.")] [Microsoft.Graph.PowerShell.Runtime.Info( Required = false, ReadOnly = false, - Description = @"List all pages", - SerializedName = @"$all", + Description = @"The page size of results.", PossibleTypes = new[] { typeof(global::System.Management.Automation.SwitchParameter) })] [global::Microsoft.Graph.PowerShell.Category(global::Microsoft.Graph.PowerShell.ParameterCategory.Runtime)] - public global::System.Management.Automation.SwitchParameter All { get => this._all; set => this._all = value; } + public int PageSize { get => this._pageSize; set => this._pageSize = value; } /// /// Default number of items per page. @@ -30,11 +31,6 @@ public partial class ListCmdlet : global::System.Management.Automation.PSCmdlet /// internal const int MaxPageSize = 999; - /// - /// Original page size/top/limit passed to Cmdlet via parameter. - /// - internal int originalPageSize = 0; - /// /// Total number of pages required to iterate page collections excluding overflow items. /// @@ -56,26 +52,47 @@ public partial class ListCmdlet : global::System.Management.Automation.PSCmdlet /// internal int totalFetchedItems = 0; + /// + /// Total number of items to be fetched. + /// + internal int limit = default; + /// /// Initializes paging values. /// /// A reference to object. - /// A reference to page size parameter. - public void InitializePaging(ref global::System.Management.Automation.InvocationInfo invocationInfo, ref int PageSize) + /// A reference to top parameter. + public void InitializePaging(ref global::System.Management.Automation.InvocationInfo invocationInfo, ref int top) { - if (PageSize > MaxPageSize) + if (invocationInfo.BoundParameters.ContainsKey("PageSize") && (PageSize > MaxPageSize || PageSize == default)) + { + ThrowTerminatingError( + new ErrorRecord( + new ArgumentException($"Invalid page size specified `{PageSize}`. {nameof(PageSize)} must be between 1 and {MaxPageSize} inclusive."), + Guid.NewGuid().ToString(), + ErrorCategory.InvalidArgument, + null)); + } + + // Move `-Top` parameter to `limit` parameter. + if (invocationInfo.BoundParameters.ContainsKey("Top")) { - invocationInfo.BoundParameters["All"] = true; - originalPageSize = PageSize; - requiredPages = PageSize / DefaultPageSize; - overflowItemsCount = PageSize % DefaultPageSize; - invocationInfo.BoundParameters["PageSize"] = DefaultPageSize; - PageSize = DefaultPageSize; + limit = top; + } + + // Explicitly set `-PageSize` as our $top parameter. + invocationInfo.BoundParameters["Top"] = invocationInfo.BoundParameters.ContainsKey("PageSize") ? PageSize : DefaultPageSize; + top = (int)invocationInfo.BoundParameters["Top"]; + + if (limit != default) + { + requiredPages = limit / top; + overflowItemsCount = limit % top; } } /// - /// Determines whether the cmdlet should follow the OData next link url. + /// Determines whether the cmdlet should follow the OData next link URI. /// /// The bound parameters of the cmdlet. /// Current page items count. @@ -84,15 +101,8 @@ public bool ShouldIteratePages(global::System.Collections.Generic.Dictionary From d4f87979970891891870e4dcd3bb6c8fe155a9d5 Mon Sep 17 00:00:00 2001 From: Peter Ombwa Date: Mon, 13 Jul 2020 11:10:05 -0700 Subject: [PATCH 7/7] Add -All parameter. --- tools/Custom/ListCmdlet.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/Custom/ListCmdlet.cs b/tools/Custom/ListCmdlet.cs index 7a54a1f66fe..174a7a6cb20 100644 --- a/tools/Custom/ListCmdlet.cs +++ b/tools/Custom/ListCmdlet.cs @@ -17,10 +17,23 @@ public partial class ListCmdlet : global::System.Management.Automation.PSCmdlet Required = false, ReadOnly = false, Description = @"The page size of results.", - PossibleTypes = new[] { typeof(global::System.Management.Automation.SwitchParameter) })] + PossibleTypes = new[] { typeof(int) })] [global::Microsoft.Graph.PowerShell.Category(global::Microsoft.Graph.PowerShell.ParameterCategory.Runtime)] public int PageSize { get => this._pageSize; set => this._pageSize = value; } + /// Backing field for property. + private global::System.Management.Automation.SwitchParameter _all; + + /// List All pages + [global::System.Management.Automation.Parameter(Mandatory = false, HelpMessage = "List all pages.")] + [Microsoft.Graph.PowerShell.Runtime.Info( + Required = false, + ReadOnly = false, + Description = @"List all pages.", + PossibleTypes = new[] { typeof(global::System.Management.Automation.SwitchParameter) })] + [global::Microsoft.Graph.PowerShell.Category(global::Microsoft.Graph.PowerShell.ParameterCategory.Runtime)] + public global::System.Management.Automation.SwitchParameter All { get => this._all; set => this._all = value; } + /// /// Default number of items per page. /// @@ -104,7 +117,7 @@ public bool ShouldIteratePages(global::System.Collections.Generic.Dictionary