├── .gitignore ├── LICENSE ├── Orders-GraphQL.sln ├── Orders ├── Models │ ├── Customer.cs │ ├── Order.cs │ ├── OrderCreateInput.cs │ └── OrderEvent.cs ├── Orders.csproj ├── Schema │ ├── CustomerType.cs │ ├── OrderCreateInputType.cs │ ├── OrderEventType.cs │ ├── OrderStatusesEnum.cs │ ├── OrderType.cs │ ├── OrdersMutation.cs │ ├── OrdersQuery.cs │ ├── OrdersSchema.cs │ └── OrdersSubscription.cs └── Services │ ├── CustomerService.cs │ ├── OrderEventService.cs │ └── OrderService.cs ├── README.MD └── Server ├── Program.cs ├── Server.csproj ├── Startup.cs └── wwwroot ├── graphiql.css ├── graphiql.js ├── graphiql.min.js └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | .vscode/ 7 | 8 | # User-specific files 9 | *.suo 10 | *.user 11 | *.userosscache 12 | *.sln.docstates 13 | 14 | # User-specific files (MonoDevelop/Xamarin Studio) 15 | *.userprefs 16 | 17 | # Build results 18 | [Dd]ebug/ 19 | [Dd]ebugPublic/ 20 | [Rr]elease/ 21 | [Rr]eleases/ 22 | x64/ 23 | x86/ 24 | bld/ 25 | [Bb]in/ 26 | [Oo]bj/ 27 | [Ll]og/ 28 | 29 | # Visual Studio 2015 cache/options directory 30 | .vs/ 31 | # Uncomment if you have tasks that create the project's static files in wwwroot 32 | #wwwroot/ 33 | 34 | # MSTest test Results 35 | [Tt]est[Rr]esult*/ 36 | [Bb]uild[Ll]og.* 37 | 38 | # NUNIT 39 | *.VisualState.xml 40 | TestResult.xml 41 | 42 | # Build Results of an ATL Project 43 | [Dd]ebugPS/ 44 | [Rr]eleasePS/ 45 | dlldata.c 46 | 47 | # .NET Core 48 | project.lock.json 49 | project.fragment.lock.json 50 | artifacts/ 51 | **/Properties/launchSettings.json 52 | 53 | *_i.c 54 | *_p.c 55 | *_i.h 56 | *.ilk 57 | *.meta 58 | *.obj 59 | *.pch 60 | *.pdb 61 | *.pgc 62 | *.pgd 63 | *.rsp 64 | *.sbr 65 | *.tlb 66 | *.tli 67 | *.tlh 68 | *.tmp 69 | *.tmp_proj 70 | *.log 71 | *.vspscc 72 | *.vssscc 73 | .builds 74 | *.pidb 75 | *.svclog 76 | *.scc 77 | 78 | # Chutzpah Test files 79 | _Chutzpah* 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opendb 86 | *.opensdf 87 | *.sdf 88 | *.cachefile 89 | *.VC.db 90 | *.VC.VC.opendb 91 | 92 | # Visual Studio profiler 93 | *.psess 94 | *.vsp 95 | *.vspx 96 | *.sap 97 | 98 | # TFS 2012 Local Workspace 99 | $tf/ 100 | 101 | # Guidance Automation Toolkit 102 | *.gpState 103 | 104 | # ReSharper is a .NET coding add-in 105 | _ReSharper*/ 106 | *.[Rr]e[Ss]harper 107 | *.DotSettings.user 108 | 109 | # JustCode is a .NET coding add-in 110 | .JustCode 111 | 112 | # TeamCity is a build add-in 113 | _TeamCity* 114 | 115 | # DotCover is a Code Coverage Tool 116 | *.dotCover 117 | 118 | # Visual Studio code coverage results 119 | *.coverage 120 | *.coveragexml 121 | 122 | # NCrunch 123 | _NCrunch_* 124 | .*crunch*.local.xml 125 | nCrunchTemp_* 126 | 127 | # MightyMoose 128 | *.mm.* 129 | AutoTest.Net/ 130 | 131 | # Web workbench (sass) 132 | .sass-cache/ 133 | 134 | # Installshield output folder 135 | [Ee]xpress/ 136 | 137 | # DocProject is a documentation generator add-in 138 | DocProject/buildhelp/ 139 | DocProject/Help/*.HxT 140 | DocProject/Help/*.HxC 141 | DocProject/Help/*.hhc 142 | DocProject/Help/*.hhk 143 | DocProject/Help/*.hhp 144 | DocProject/Help/Html2 145 | DocProject/Help/html 146 | 147 | # Click-Once directory 148 | publish/ 149 | 150 | # Publish Web Output 151 | *.[Pp]ublish.xml 152 | *.azurePubxml 153 | # TODO: Comment the next line if you want to checkin your web deploy settings 154 | # but database connection strings (with potential passwords) will be unencrypted 155 | *.pubxml 156 | *.publishproj 157 | 158 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 159 | # checkin your Azure Web App publish settings, but sensitive information contained 160 | # in these scripts will be unencrypted 161 | PublishScripts/ 162 | 163 | # NuGet Packages 164 | *.nupkg 165 | # The packages folder can be ignored because of Package Restore 166 | **/packages/* 167 | # except build/, which is used as an MSBuild target. 168 | !**/packages/build/ 169 | # Uncomment if necessary however generally it will be regenerated when needed 170 | #!**/packages/repositories.config 171 | # NuGet v3's project.json files produces more ignorable files 172 | *.nuget.props 173 | *.nuget.targets 174 | 175 | # Microsoft Azure Build Output 176 | csx/ 177 | *.build.csdef 178 | 179 | # Microsoft Azure Emulator 180 | ecf/ 181 | rcf/ 182 | 183 | # Windows Store app package directories and files 184 | AppPackages/ 185 | BundleArtifacts/ 186 | Package.StoreAssociation.xml 187 | _pkginfo.txt 188 | 189 | # Visual Studio cache files 190 | # files ending in .cache can be ignored 191 | *.[Cc]ache 192 | # but keep track of directories ending in .cache 193 | !*.[Cc]ache/ 194 | 195 | # Others 196 | ClientBin/ 197 | ~$* 198 | *~ 199 | *.dbmdl 200 | *.dbproj.schemaview 201 | *.jfm 202 | *.pfx 203 | *.publishsettings 204 | orleans.codegen.cs 205 | 206 | # Since there are multiple workflows, uncomment next line to ignore bower_components 207 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 208 | #bower_components/ 209 | 210 | # RIA/Silverlight projects 211 | Generated_Code/ 212 | 213 | # Backup & report files from converting an old project file 214 | # to a newer Visual Studio version. Backup files are not needed, 215 | # because we have git ;-) 216 | _UpgradeReport_Files/ 217 | Backup*/ 218 | UpgradeLog*.XML 219 | UpgradeLog*.htm 220 | 221 | # SQL Server files 222 | *.mdf 223 | *.ldf 224 | *.ndf 225 | 226 | # Business Intelligence projects 227 | *.rdl.data 228 | *.bim.layout 229 | *.bim_*.settings 230 | 231 | # Microsoft Fakes 232 | FakesAssemblies/ 233 | 234 | # GhostDoc plugin setting file 235 | *.GhostDoc.xml 236 | 237 | # Node.js Tools for Visual Studio 238 | .ntvs_analysis.dat 239 | node_modules/ 240 | 241 | # Typescript v1 declaration files 242 | typings/ 243 | 244 | # Visual Studio 6 build log 245 | *.plg 246 | 247 | # Visual Studio 6 workspace options file 248 | *.opt 249 | 250 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 251 | *.vbw 252 | 253 | # Visual Studio LightSwitch build output 254 | **/*.HTMLClient/GeneratedArtifacts 255 | **/*.DesktopClient/GeneratedArtifacts 256 | **/*.DesktopClient/ModelManifest.xml 257 | **/*.Server/GeneratedArtifacts 258 | **/*.Server/ModelManifest.xml 259 | _Pvt_Extensions 260 | 261 | # Paket dependency manager 262 | .paket/paket.exe 263 | paket-files/ 264 | 265 | # FAKE - F# Make 266 | .fake/ 267 | 268 | # JetBrains Rider 269 | .idea/ 270 | *.sln.iml 271 | 272 | # CodeRush 273 | .cr/ 274 | 275 | # Python Tools for Visual Studio (PTVS) 276 | __pycache__/ 277 | *.pyc 278 | 279 | # Cake - Uncomment if you are using it 280 | # tools/** 281 | # !tools/packages.config 282 | 283 | # Telerik's JustMock configuration file 284 | *.jmconfig 285 | 286 | # BizTalk build output 287 | *.btp.cs 288 | *.btm.cs 289 | *.odx.cs 290 | *.xsd.cs -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Orders-GraphQL.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2020 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{59A54287-7074-49AA-A008-D5EECDE28B03}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Orders", "Orders\Orders.csproj", "{E9E34DB4-347F-49C8-8838-DFD35C0BCD0C}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {59A54287-7074-49AA-A008-D5EECDE28B03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {59A54287-7074-49AA-A008-D5EECDE28B03}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {59A54287-7074-49AA-A008-D5EECDE28B03}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {59A54287-7074-49AA-A008-D5EECDE28B03}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {E9E34DB4-347F-49C8-8838-DFD35C0BCD0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {E9E34DB4-347F-49C8-8838-DFD35C0BCD0C}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {E9E34DB4-347F-49C8-8838-DFD35C0BCD0C}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {E9E34DB4-347F-49C8-8838-DFD35C0BCD0C}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {1D545C02-0133-4F38-9D1F-4DA3BD5E4DC6} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Orders/Models/Customer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Orders.Models 6 | { 7 | public class Customer 8 | { 9 | public Customer(int id, string name) 10 | { 11 | Id = id; 12 | Name = name; 13 | } 14 | 15 | public int Id { get; } 16 | public string Name { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Orders/Models/Order.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Orders.Models 6 | { 7 | public class Order 8 | { 9 | public Order(string name, string description, DateTime created, int customerId, string Id) 10 | { 11 | Name = name; 12 | Description = description; 13 | Created = created; 14 | CustomerId = customerId; 15 | this.Id = Id; 16 | Status = OrderStatuses.CREATED; 17 | } 18 | 19 | public string Name { get; set; } 20 | public string Description { get; set; } 21 | public DateTime Created { get; private set; } 22 | public int CustomerId { get; set; } 23 | public string Id { get; private set; } 24 | public OrderStatuses Status { get; private set; } 25 | 26 | public void Start() 27 | { 28 | if (Status != OrderStatuses.CREATED) { 29 | throw new InvalidOperationException(string.Format("Order: {0} cannot be started", Id)); 30 | } 31 | Status = OrderStatuses.PROCESSING; 32 | } 33 | 34 | public void Complete() { 35 | if (Status != OrderStatuses.PROCESSING) { 36 | throw new InvalidOperationException(string.Format("Order: {0} cannot be completed", Id)); 37 | } 38 | 39 | Status = OrderStatuses.COMPLETED; 40 | } 41 | 42 | public void Cancel() { 43 | if (Status == OrderStatuses.CANCELLED || Status == OrderStatuses.CLOSED || Status == OrderStatuses.COMPLETED) { 44 | throw new InvalidOperationException(string.Format("Order: {0} cannot be cancelled", Id)); 45 | } 46 | 47 | Status = OrderStatuses.CANCELLED; 48 | } 49 | 50 | public void Close() { 51 | if (Status != OrderStatuses.COMPLETED) { 52 | throw new InvalidOperationException(string.Format("Order: {0} cannot be closed", Id)); 53 | } 54 | 55 | Status = OrderStatuses.CLOSED; 56 | } 57 | 58 | 59 | } 60 | 61 | [Flags] 62 | public enum OrderStatuses 63 | { 64 | CREATED = 2, 65 | PROCESSING = 4, 66 | COMPLETED = 8, 67 | CANCELLED = 16, 68 | CLOSED = 32 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Orders/Models/OrderCreateInput.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Orders.Models 6 | { 7 | public class OrderCreateInput 8 | { 9 | public string Name { get; set; } 10 | public string Description { get; set; } 11 | public int CustomerId { get; set; } 12 | public DateTime Created { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Orders/Models/OrderEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Orders.Models 6 | { 7 | public class OrderEvent 8 | { 9 | public OrderEvent(string orderId, string name, OrderStatuses status, DateTime timestamp) 10 | { 11 | OrderId = orderId; 12 | Name = name; 13 | Status = status; 14 | Timestamp = timestamp; 15 | Id = Guid.NewGuid().ToString(); 16 | } 17 | public string Id { get; set; } 18 | public string OrderId { get; set; } 19 | public string Name { get; set; } 20 | public OrderStatuses Status { get; set; } 21 | public DateTime Timestamp { get; private set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Orders/Orders.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Orders/Schema/CustomerType.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using Orders.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace Orders.Schema 8 | { 9 | public class CustomerType : ObjectGraphType 10 | { 11 | public CustomerType() 12 | { 13 | Field(c => c.Id); 14 | Field(c => c.Name); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Orders/Schema/OrderCreateInputType.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Orders.Schema 7 | { 8 | public class OrderCreateInputType : InputObjectGraphType 9 | { 10 | public OrderCreateInputType() 11 | { 12 | Name = "OrderInput"; 13 | Field>("name"); 14 | Field>("description"); 15 | Field>("customerId"); 16 | Field>("created"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Orders/Schema/OrderEventType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using GraphQL.Types; 5 | using Orders.Models; 6 | 7 | namespace Orders.Schema 8 | { 9 | public class OrderEventType : ObjectGraphType 10 | { 11 | public OrderEventType() 12 | { 13 | Field(e => e.Id); 14 | Field(e => e.Name); 15 | Field(e => e.OrderId); 16 | Field("status", 17 | resolve: context => context.Source.Status); 18 | Field(e => e.Timestamp); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Orders/Schema/OrderStatusesEnum.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Orders.Schema 7 | { 8 | public class OrderStatusesEnum : EnumerationGraphType 9 | { 10 | public OrderStatusesEnum() 11 | { 12 | Name = "OrderStatuses"; 13 | AddValue("CREATED", "Order was created", 2); 14 | AddValue("PROCESSING", "Order is being processed", 4); 15 | AddValue("COMPLETED", "Order is completed", 8); 16 | AddValue("CANCELLED", "Order was cancelled", 16); 17 | AddValue("CLOSED", "Order was closed", 32); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Orders/Schema/OrderType.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using Orders.Models; 3 | using Orders.Services; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace Orders.Schema 9 | { 10 | public class OrderType : ObjectGraphType 11 | { 12 | public OrderType(ICustomerService customers) 13 | { 14 | Field(o => o.Id); 15 | Field(o => o.Name); 16 | Field(o => o.Description); 17 | Field("customer", 18 | resolve: context => customers.GetCustomerByIdAsync(context.Source.CustomerId)); 19 | Field(o => o.Created); 20 | Field("status", 21 | resolve: context => context.Source.Status); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Orders/Schema/OrdersMutation.cs: -------------------------------------------------------------------------------- 1 | using GraphQL; 2 | using GraphQL.Types; 3 | using Orders.Models; 4 | using Orders.Services; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace Orders.Schema 10 | { 11 | public class OrdersMutation : ObjectGraphType 12 | { 13 | public OrdersMutation(IOrderService orders) 14 | { 15 | Name = "Mutation"; 16 | Field( 17 | "createOrder", 18 | arguments: new QueryArguments( 19 | new QueryArgument> { Name = "order" }), 20 | resolve: context => 21 | { 22 | var orderInput = context.GetArgument("order"); 23 | var id = Guid.NewGuid().ToString(); 24 | var order = new Order(orderInput.Name, orderInput.Description, orderInput.Created, orderInput.CustomerId, id); 25 | return orders.CreateAsync(order); 26 | } 27 | ); 28 | 29 | FieldAsync( 30 | "startOrder", 31 | arguments: new QueryArguments(new QueryArgument> { Name = "orderId" }), 32 | resolve: async context => 33 | { 34 | var orderId = context.GetArgument("orderId"); 35 | return await context.TryAsyncResolve( 36 | async c => await orders.StartAsync(orderId)); 37 | } 38 | ); 39 | 40 | FieldAsync( 41 | "completeOrder", 42 | arguments: new QueryArguments(new QueryArgument> { Name = "orderId" }), 43 | resolve: async context => 44 | { 45 | var orderId = context.GetArgument("orderId"); 46 | return await context.TryAsyncResolve( 47 | async c => await orders.CompleteAsync(orderId)); 48 | } 49 | ); 50 | 51 | FieldAsync( 52 | "cancelOrder", 53 | arguments: new QueryArguments(new QueryArgument> { Name = "orderId" }), 54 | resolve: async context => 55 | { 56 | var orderId = context.GetArgument("orderId"); 57 | return await context.TryAsyncResolve( 58 | async c => await orders.CancelAsync(orderId)); 59 | } 60 | ); 61 | 62 | FieldAsync( 63 | "closeOrder", 64 | arguments: new QueryArguments(new QueryArgument> { Name = "orderId" }), 65 | resolve: async context => 66 | { 67 | var orderId = context.GetArgument("orderId"); 68 | return await context.TryAsyncResolve( 69 | async c => await orders.CloseAsync(orderId)); 70 | } 71 | ); 72 | 73 | 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Orders/Schema/OrdersQuery.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using System.Linq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using Orders.Services; 7 | 8 | namespace Orders.Schema 9 | { 10 | public class OrdersQuery : ObjectGraphType 11 | { 12 | public OrdersQuery(IOrderService orders, ICustomerService customers) 13 | { 14 | Name = "Query"; 15 | Field>( 16 | "orders", 17 | resolve: context => orders.GetOrdersAsync() 18 | ); 19 | 20 | FieldAsync( 21 | "orderById", 22 | arguments: new QueryArguments(new QueryArgument> {Name="orderId"}), 23 | resolve: async context => { 24 | return await context.TryAsyncResolve( 25 | async c=> await orders.GetOrderByIdAsync(c.GetArgument("orderId")) 26 | ); 27 | } 28 | ); 29 | 30 | Field>( 31 | "customers", 32 | resolve: context => customers.GetCustomersAsync() 33 | ); 34 | 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Orders/Schema/OrdersSchema.cs: -------------------------------------------------------------------------------- 1 | using GraphQL; 2 | using GraphQL.Types; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace Orders.Schema 8 | { 9 | public class OrdersSchema : GraphQL.Types.Schema 10 | { 11 | public OrdersSchema(OrdersQuery query, OrdersMutation mutation, OrdersSubscription subscription, IDependencyResolver resolver) 12 | { 13 | Query = query; 14 | Mutation = mutation; 15 | Subscription = subscription; 16 | DependencyResolver = resolver; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Orders/Schema/OrdersSubscription.cs: -------------------------------------------------------------------------------- 1 | using GraphQL.Types; 2 | using GraphQL.Subscription; 3 | using GraphQL.Resolvers; 4 | using Orders.Services; 5 | using Orders.Models; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Text; 9 | using System.Reactive.Linq; 10 | 11 | namespace Orders.Schema 12 | { 13 | public class OrdersSubscription : ObjectGraphType 14 | { 15 | private readonly IOrderEventService _events; 16 | 17 | public OrdersSubscription(IOrderEventService events) 18 | { 19 | _events = events; 20 | Name = "Subscription"; 21 | AddField(new EventStreamFieldType 22 | { 23 | Name = "orderEvent", 24 | Arguments = new QueryArguments(new QueryArgument> 25 | { 26 | Name = "statuses" 27 | }), 28 | Type = typeof(OrderEventType), 29 | Resolver = new FuncFieldResolver(ResolveEvent), 30 | Subscriber = new EventStreamResolver(Subscribe) 31 | }); 32 | } 33 | 34 | private OrderEvent ResolveEvent(ResolveFieldContext context) 35 | { 36 | var orderEvent = context.Source as OrderEvent; 37 | return orderEvent; 38 | } 39 | 40 | private IObservable Subscribe(ResolveEventStreamContext context) 41 | { 42 | var statusList = context.GetArgument>("statuses", new List()); 43 | 44 | if (statusList.Count > 0) 45 | { 46 | OrderStatuses statuses = 0; 47 | 48 | foreach(var status in statusList) 49 | { 50 | statuses = statuses | status; 51 | } 52 | return _events.EventStream().Where(e => (e.Status & statuses) == e.Status); 53 | } 54 | else 55 | { 56 | return _events.EventStream(); 57 | } 58 | 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Orders/Services/CustomerService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Orders.Models; 7 | 8 | namespace Orders.Services 9 | { 10 | public class CustomerService : ICustomerService 11 | { 12 | private IList _customers; 13 | 14 | public CustomerService() 15 | { 16 | _customers = new List(); 17 | _customers.Add(new Customer(1, "KinetEco")); 18 | _customers.Add(new Customer(2, "Pixelford Photography")); 19 | _customers.Add(new Customer(3, "Topsy Turvy")); 20 | _customers.Add(new Customer(4, "Leaf & Mortar")); 21 | } 22 | 23 | public Customer GetCustomerById(int id) 24 | { 25 | return GetCustomerByIdAsync(id).Result; 26 | } 27 | 28 | public Task GetCustomerByIdAsync(int id) 29 | { 30 | return Task.FromResult(_customers.Single(o => Equals(o.Id, id))); 31 | } 32 | 33 | public Task> GetCustomersAsync() 34 | { 35 | return Task.FromResult(_customers.AsEnumerable()); 36 | } 37 | } 38 | 39 | public interface ICustomerService 40 | { 41 | Customer GetCustomerById(int id); 42 | Task GetCustomerByIdAsync(int id); 43 | Task> GetCustomersAsync(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Orders/Services/OrderEventService.cs: -------------------------------------------------------------------------------- 1 | using Orders.Models; 2 | using System; 3 | using System.Collections.Concurrent; 4 | using System.Collections.Generic; 5 | using System.Reactive.Linq; 6 | using System.Reactive.Subjects; 7 | using System.Text; 8 | 9 | namespace Orders.Services 10 | { 11 | public class OrderEventService : IOrderEventService 12 | { 13 | private readonly ISubject _eventStream = new ReplaySubject(1); 14 | 15 | public OrderEventService() 16 | { 17 | AllEvents = new ConcurrentStack(); 18 | } 19 | 20 | public ConcurrentStack AllEvents { get; } 21 | 22 | public void AddError(Exception exception) 23 | { 24 | _eventStream.OnError(exception); 25 | } 26 | 27 | public OrderEvent AddEvent(OrderEvent orderEvent) 28 | { 29 | AllEvents.Push(orderEvent); 30 | _eventStream.OnNext(orderEvent); 31 | return orderEvent; 32 | } 33 | 34 | public IObservable EventStream() 35 | { 36 | return _eventStream.AsObservable(); 37 | } 38 | } 39 | 40 | public interface IOrderEventService 41 | { 42 | ConcurrentStack AllEvents { get; } 43 | void AddError(Exception exception); 44 | OrderEvent AddEvent(OrderEvent orderEvent); 45 | IObservable EventStream(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Orders/Services/OrderService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Orders.Models; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Orders.Services 9 | { 10 | public class OrderService : IOrderService 11 | { 12 | private IList _orders; 13 | private readonly IOrderEventService _events; 14 | 15 | public OrderService(IOrderEventService events) 16 | { 17 | _orders = new List(); 18 | _orders.Add(new Order("1000", "250 Conference brochures", DateTime.Now, 1, "FAEBD971-CBA5-4CED-8AD5-CC0B8D4B7827")); 19 | _orders.Add(new Order("2000", "250 T-shirts", DateTime.Now.AddDays(-1), 2, "F43A4F9D-7AE9-4A19-93D9-2018387D5378")); 20 | _orders.Add(new Order("3000", "500 Stickers", DateTime.Now.AddDays(-1), 3, "2D542571-EF99-4786-AEB5-C997D82E57C7")); 21 | _orders.Add(new Order("4000", "10 Posters", DateTime.Now.AddDays(-1), 1, "8F2E3A32-EF09-45E7-88E9-6F62EBC47548")); 22 | _orders.Add(new Order("5000", "150 Hats", DateTime.Now.AddDays(-2), 2, "41D73692-104B-4615-AA10-B6F5B51BFAF5")); 23 | _orders.Add(new Order("6000", "750 Keychains", DateTime.Now.AddDays(-2), 3, "6E431741-F049-4B1A-BC64-408986BD209A")); 24 | _orders.Add(new Order("7000", "5 Drones", DateTime.Now.AddDays(-2), 1, "17EF9022-8D38-42F7-A21B-3A41847005FD")); 25 | _orders.Add(new Order("8000", "10 Posters", DateTime.Now.AddDays(-3), 2, "B34B06E2-8E27-4DFC-B7B3-D0282BA34F8A")); 26 | _orders.Add(new Order("9000", "200 Pens", DateTime.Now.AddDays(-3), 3, "18E6242C-4A9E-4741-A962-DFB02958BBCB")); 27 | _orders.Add(new Order("10000", "500 Business cards", DateTime.Now.AddDays(-3), 1, "FF10F49B-A2EB-473A-A52F-AA63F30D7ED1")); 28 | _orders.Add(new Order("11000", "250 Pins", DateTime.Now.AddDays(-4), 2, "88F6D29C-4CDC-48DF-B41C-D5801EC0B980")); 29 | _orders.Add(new Order("12000", "500 Coffee Sleeves", DateTime.Now.AddDays(-4), 3, "CDD0FC42-7605-4874-B175-161F4E2606D5")); 30 | _orders.Add(new Order("13000", "400 Pads", DateTime.Now.AddDays(-4), 1, "7E4A1B65-54A1-4782-A7D5-3834F02B1DE1")); 31 | _orders.Add(new Order("14000", "100 Bandanas", DateTime.Now.AddDays(-5), 2, "89D53FE2-1F26-4568-A0C6-370280802647")); 32 | _orders.Add(new Order("15000", "50 Spinners", DateTime.Now.AddDays(-5), 3, "75803E03-0100-4A47-91F5-CF7F5738B89B")); 33 | this._events = events; 34 | } 35 | 36 | private Order GetById(string id) 37 | { 38 | var order = _orders.SingleOrDefault(o => Equals(o.Id, id)); 39 | if (order == null) 40 | { 41 | throw new ArgumentException(string.Format("Order ID '{0}' is invalid", id)); 42 | } 43 | return order; 44 | } 45 | 46 | 47 | public Task CreateAsync(Order order) 48 | { 49 | _orders.Add(order); 50 | var orderEvent = new OrderEvent(order.Id, order.Name, OrderStatuses.CREATED,DateTime.Now); 51 | _events.AddEvent(orderEvent); 52 | return Task.FromResult(order); 53 | throw new NotImplementedException(); 54 | } 55 | 56 | public Task GetOrderByIdAsync(string id) 57 | { 58 | return Task.FromResult(GetById(id)); 59 | } 60 | 61 | public Task> GetOrdersAsync() 62 | { 63 | return Task.FromResult(_orders.AsEnumerable()); 64 | } 65 | 66 | public Task StartAsync(string orderId) 67 | { 68 | var order = GetById(orderId); 69 | order.Start(); 70 | var orderEvent = new OrderEvent(order.Id, order.Name, OrderStatuses.PROCESSING, DateTime.Now); 71 | _events.AddEvent(orderEvent); 72 | return Task.FromResult(order); 73 | } 74 | 75 | public Task CompleteAsync(string orderId) 76 | { 77 | var order = GetById(orderId); 78 | order.Complete(); 79 | var orderEvent = new OrderEvent(order.Id, order.Name, OrderStatuses.COMPLETED, DateTime.Now); 80 | _events.AddEvent(orderEvent); 81 | return Task.FromResult(order); 82 | } 83 | 84 | public Task CancelAsync(string orderId) 85 | { 86 | var order = GetById(orderId); 87 | order.Cancel(); 88 | var orderEvent = new OrderEvent(order.Id, order.Name, OrderStatuses.CANCELLED, DateTime.Now); 89 | _events.AddEvent(orderEvent); 90 | return Task.FromResult(order); 91 | } 92 | 93 | public Task CloseAsync(string orderId) 94 | { 95 | var order = GetById(orderId); 96 | order.Close(); 97 | var orderEvent = new OrderEvent(order.Id, order.Name, OrderStatuses.CLOSED, DateTime.Now); 98 | _events.AddEvent(orderEvent); 99 | return Task.FromResult(order); 100 | } 101 | } 102 | 103 | public interface IOrderService 104 | { 105 | Task GetOrderByIdAsync(string id); 106 | Task> GetOrdersAsync(); 107 | Task CreateAsync(Order order); 108 | Task StartAsync(string orderId); 109 | Task CompleteAsync(string orderId); 110 | Task CancelAsync(string orderId); 111 | Task CloseAsync(string orderId); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # Example-Orders 2 | A sample GraphQL order management endpoint using GraphQL for .NET. This is a more advanced version of the example I used in my course [API Development in .NET with GraphQL](https://www.lynda.com/NET-tutorials/API-Development-NET-GraphQL/664823-2.html) 3 | 4 | ## Running the sample 5 | * If using Visual Studio, open `Orders-GraphQL.sln` build and run 6 | * On Mac/Linux go the `Server` folder and run `dotnet run -f netcoreapp2.0` 7 | 8 | ## Overview 9 | This endpoint contains 2 core data types 10 | * Orders - Orders that have been added to the system 11 | * Customers - Customers for each order 12 | 13 | ## API 14 | ### Queries 15 | #### orders 16 | Retrieves a list of orders 17 | 18 | example: 19 | ``` 20 | query getOrders { 21 | orders { 22 | id 23 | name 24 | description 25 | customer { 26 | name 27 | } 28 | } 29 | } 30 | ``` 31 | #### orderById 32 | Retrieves a specified order 33 | 34 | *Arguments* 35 | * orderId - The id of the order 36 | 37 | example: 38 | ``` 39 | query getOrder { 40 | orderById(orderId: "FAEBD971-CBA5-4CED-8AD5-CC0B8D4B7827") { 41 | id 42 | name 43 | description 44 | } 45 | } 46 | ``` 47 | #### customers 48 | Retrieves all customers 49 | 50 | example: 51 | ``` 52 | query getCustomers { 53 | customers { 54 | id 55 | name 56 | } 57 | } 58 | ``` 59 | ### Mutations 60 | #### createOrder 61 | Creates an order 62 | 63 | *Arguments* 64 | * order - Information for the order to be created. 65 | 66 | example: 67 | ``` 68 | mutation createOrder{ 69 | createOrder(order: 70 | { 71 | name:"Glenn", 72 | description:"Test", 73 | customerId: 1, 74 | created: "03/16/2018" 75 | } 76 | ) 77 | { 78 | id 79 | name 80 | } 81 | } 82 | ``` 83 | #### startOrder 84 | Starts the processing of an order. Can only be called if the order is in a `CREATED` state. 85 | 86 | *Arguments* 87 | * orderId - The id of the order 88 | 89 | example starting an order 90 | ``` 91 | mutation startOrder { 92 | startOrder(orderId: "FAEBD971-CBA5-4CED-8AD5-CC0B8D4B7827") { 93 | id 94 | status 95 | } 96 | } 97 | ``` 98 | #### completeOrder 99 | Finishes the processing of an order. Can only be called if the order is in the `PROCESSING` state. 100 | 101 | *Arguments* 102 | * orderId - The id of the order 103 | 104 | example completing an order 105 | ``` 106 | mutation completeOrder { 107 | completeOrder(orderId: "FAEBD971-CBA5-4CED-8AD5-CC0B8D4B7827") { 108 | id 109 | status 110 | } 111 | } 112 | ``` 113 | #### cancelOrder 114 | Cancels an order. Can only be called if the order is not in the `COMPLETED` or `CANCELLED` state. 115 | 116 | *Arguments* 117 | * orderId - The id of the order 118 | 119 | example cancelling an order 120 | ``` 121 | mutation cancelOrder { 122 | cancelOrder(orderId: "FAEBD971-CBA5-4CED-8AD5-CC0B8D4B7827") { 123 | id 124 | status 125 | } 126 | } 127 | ``` 128 | #### closeOrder 129 | Closes an order. Can only be called if the order is in the `COMPLETED` state. 130 | 131 | *Arguments* 132 | * orderId - The id of the order 133 | 134 | example closing an order 135 | ``` 136 | mutation closeOrder { 137 | closeOrder(orderId: "FAEBD971-CBA5-4CED-8AD5-CC0B8D4B7827") { 138 | id 139 | status 140 | } 141 | } 142 | ``` 143 | ### Subscriptions 144 | You can use subscriptions to get notified when an order is created. This relies on the awesome [GraphQL Server](https://github.com/graphql-dotnet/server) project. 145 | 146 | To test out subscriptions, you'll want to open two graphiql instances. One for subscribing, and the other for performing a mutation. 147 | 148 | #### orderEvent 149 | Notifies when order status changes. 150 | 151 | *Arguments* 152 | * statuses (optional) - An array of one or more statuses to receive notifications on 153 | 154 | example subscribing to all order updates 155 | ``` 156 | subscription createdEvent { 157 | orderEvent { 158 | id 159 | name 160 | status 161 | } 162 | } 163 | ``` 164 | 165 | example subscribing to order started events 166 | ``` 167 | subscription startedEvent { 168 | orderEvent ([PROCESSING]) { 169 | id 170 | name 171 | status 172 | } 173 | } 174 | ``` 175 | 176 | ## Solution Structure 177 | * Server - Contains the GraphQL Server / wires up GraphQL.NET middleware 178 | * Orders - Contains models and the GraphQL Schema 179 | * Models - Contains the underlying models which drive the schema 180 | * Services - Contains data services for retrieving and updating models, as well as for notifications. Services are registered with the ASP.NET Core container allowing them to be injected wherever need. 181 | * Schema - Contains the GraphQL types, queries, mutuations and subscriptions. 182 | 183 | ## License 184 | Apache 2.0 185 | 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /Server/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace Server 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | BuildWebHost(args).Run(); 18 | } 19 | 20 | public static IWebHost BuildWebHost(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup() 23 | .Build(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Server/Server.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0;net461 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Server/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using GraphQL; 6 | using GraphQL.Server; 7 | using GraphQL.Server.Ui.GraphiQL; 8 | using GraphQL.Server.Ui.Playground; 9 | using GraphQL.Server.Ui.Voyager; 10 | using Microsoft.AspNetCore.Builder; 11 | using Microsoft.AspNetCore.Hosting; 12 | using Microsoft.AspNetCore.Http; 13 | using Microsoft.Extensions.DependencyInjection; 14 | using Orders.Schema; 15 | using Orders.Services; 16 | 17 | namespace Server 18 | { 19 | public class Startup 20 | { 21 | 22 | public Startup(IHostingEnvironment environment) 23 | { 24 | Environment = environment; 25 | } 26 | 27 | public IHostingEnvironment Environment { get; } 28 | 29 | 30 | // This method gets called by the runtime. Use this method to add services to the container. 31 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 32 | public void ConfigureServices(IServiceCollection services) 33 | { 34 | services.AddSingleton(); 35 | services.AddSingleton(); 36 | services.AddTransient(); 37 | services.AddTransient(); 38 | services.AddTransient(); 39 | services.AddTransient(); 40 | services.AddTransient(); 41 | services.AddTransient(); 42 | services.AddTransient(); 43 | services.AddTransient(); 44 | services.AddTransient(); 45 | services.AddSingleton(); 46 | services.AddSingleton( 47 | c => new FuncDependencyResolver(type => c.GetRequiredService(type))); 48 | services.AddGraphQL(options=> { 49 | options.EnableMetrics = true; 50 | options.ExposeExceptions = Environment.IsDevelopment(); 51 | }) 52 | .AddWebSockets() 53 | .AddDataLoader(); 54 | } 55 | 56 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 57 | public void Configure(IApplicationBuilder app) 58 | { 59 | if (Environment.IsDevelopment()) 60 | app.UseDeveloperExceptionPage(); 61 | app.UseDefaultFiles(); 62 | app.UseStaticFiles(); 63 | app.UseWebSockets(); 64 | app.UseGraphQLWebSockets("/graphql"); 65 | app.UseGraphQL("/graphql"); 66 | app.UseGraphQLPlayground(new GraphQLPlaygroundOptions() 67 | { 68 | Path = "/ui/playground" 69 | }); 70 | app.UseGraphiQLServer(new GraphiQLOptions 71 | { 72 | GraphiQLPath = "/ui/graphiql", 73 | GraphQLEndPoint = "/graphql" 74 | }); 75 | app.UseGraphQLVoyager(new GraphQLVoyagerOptions() 76 | { 77 | GraphQLEndPoint = "/graphql", 78 | Path = "/ui/voyager" 79 | }); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Server/wwwroot/graphiql.css: -------------------------------------------------------------------------------- 1 | .graphiql-container, 2 | .graphiql-container button, 3 | .graphiql-container input { 4 | color: #141823; 5 | font-family: 6 | system, 7 | -apple-system, 8 | 'San Francisco', 9 | '.SFNSDisplay-Regular', 10 | 'Segoe UI', 11 | Segoe, 12 | 'Segoe WP', 13 | 'Helvetica Neue', 14 | helvetica, 15 | 'Lucida Grande', 16 | arial, 17 | sans-serif; 18 | font-size: 14px; 19 | } 20 | 21 | .graphiql-container { 22 | display: -webkit-box; 23 | display: -ms-flexbox; 24 | display: flex; 25 | -webkit-box-orient: horizontal; 26 | -webkit-box-direction: normal; 27 | -ms-flex-direction: row; 28 | flex-direction: row; 29 | height: 100%; 30 | margin: 0; 31 | overflow: hidden; 32 | width: 100%; 33 | } 34 | 35 | .graphiql-container .editorWrap { 36 | display: -webkit-box; 37 | display: -ms-flexbox; 38 | display: flex; 39 | -webkit-box-orient: vertical; 40 | -webkit-box-direction: normal; 41 | -ms-flex-direction: column; 42 | flex-direction: column; 43 | -webkit-box-flex: 1; 44 | -ms-flex: 1; 45 | flex: 1; 46 | } 47 | 48 | .graphiql-container .title { 49 | font-size: 18px; 50 | } 51 | 52 | .graphiql-container .title em { 53 | font-family: georgia; 54 | font-size: 19px; 55 | } 56 | 57 | .graphiql-container .topBarWrap { 58 | display: -webkit-box; 59 | display: -ms-flexbox; 60 | display: flex; 61 | -webkit-box-orient: horizontal; 62 | -webkit-box-direction: normal; 63 | -ms-flex-direction: row; 64 | flex-direction: row; 65 | } 66 | 67 | .graphiql-container .topBar { 68 | -webkit-box-align: center; 69 | -ms-flex-align: center; 70 | align-items: center; 71 | background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#e2e2e2)); 72 | background: linear-gradient(#f7f7f7, #e2e2e2); 73 | border-bottom: 1px solid #d0d0d0; 74 | cursor: default; 75 | display: -webkit-box; 76 | display: -ms-flexbox; 77 | display: flex; 78 | -webkit-box-orient: horizontal; 79 | -webkit-box-direction: normal; 80 | -ms-flex-direction: row; 81 | flex-direction: row; 82 | -webkit-box-flex: 1; 83 | -ms-flex: 1; 84 | flex: 1; 85 | height: 34px; 86 | padding: 7px 14px 6px; 87 | -webkit-user-select: none; 88 | -moz-user-select: none; 89 | -ms-user-select: none; 90 | user-select: none; 91 | } 92 | 93 | .graphiql-container .toolbar { 94 | overflow-x: visible; 95 | display: -webkit-box; 96 | display: -ms-flexbox; 97 | display: flex; 98 | } 99 | 100 | .graphiql-container .docExplorerShow, 101 | .graphiql-container .historyShow { 102 | background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#e2e2e2)); 103 | background: linear-gradient(#f7f7f7, #e2e2e2); 104 | border-bottom: 1px solid #d0d0d0; 105 | border-right: none; 106 | border-top: none; 107 | color: #3B5998; 108 | cursor: pointer; 109 | font-size: 14px; 110 | margin: 0; 111 | outline: 0; 112 | padding: 2px 20px 0 18px; 113 | } 114 | 115 | .graphiql-container .docExplorerShow { 116 | border-left: 1px solid rgba(0, 0, 0, 0.2); 117 | } 118 | 119 | .graphiql-container .historyShow { 120 | border-right: 1px solid rgba(0, 0, 0, 0.2); 121 | border-left: 0; 122 | } 123 | 124 | .graphiql-container .docExplorerShow:before { 125 | border-left: 2px solid #3B5998; 126 | border-top: 2px solid #3B5998; 127 | content: ''; 128 | display: inline-block; 129 | height: 9px; 130 | margin: 0 3px -1px 0; 131 | position: relative; 132 | -webkit-transform: rotate(-45deg); 133 | transform: rotate(-45deg); 134 | width: 9px; 135 | } 136 | 137 | .graphiql-container .editorBar { 138 | display: -webkit-box; 139 | display: -ms-flexbox; 140 | display: flex; 141 | -webkit-box-orient: horizontal; 142 | -webkit-box-direction: normal; 143 | -ms-flex-direction: row; 144 | flex-direction: row; 145 | -webkit-box-flex: 1; 146 | -ms-flex: 1; 147 | flex: 1; 148 | } 149 | 150 | .graphiql-container .queryWrap { 151 | display: -webkit-box; 152 | display: -ms-flexbox; 153 | display: flex; 154 | -webkit-box-orient: vertical; 155 | -webkit-box-direction: normal; 156 | -ms-flex-direction: column; 157 | flex-direction: column; 158 | -webkit-box-flex: 1; 159 | -ms-flex: 1; 160 | flex: 1; 161 | } 162 | 163 | .graphiql-container .resultWrap { 164 | border-left: solid 1px #e0e0e0; 165 | display: -webkit-box; 166 | display: -ms-flexbox; 167 | display: flex; 168 | -webkit-box-orient: vertical; 169 | -webkit-box-direction: normal; 170 | -ms-flex-direction: column; 171 | flex-direction: column; 172 | -webkit-box-flex: 1; 173 | -ms-flex: 1; 174 | flex: 1; 175 | position: relative; 176 | } 177 | 178 | .graphiql-container .docExplorerWrap, 179 | .graphiql-container .historyPaneWrap { 180 | background: white; 181 | -webkit-box-shadow: 0 0 8px rgba(0, 0, 0, 0.15); 182 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.15); 183 | position: relative; 184 | z-index: 3; 185 | } 186 | 187 | .graphiql-container .historyPaneWrap { 188 | min-width: 230px; 189 | z-index: 5; 190 | } 191 | 192 | .graphiql-container .docExplorerResizer { 193 | cursor: col-resize; 194 | height: 100%; 195 | left: -5px; 196 | position: absolute; 197 | top: 0; 198 | width: 10px; 199 | z-index: 10; 200 | } 201 | 202 | .graphiql-container .docExplorerHide { 203 | cursor: pointer; 204 | font-size: 18px; 205 | margin: -7px -8px -6px 0; 206 | padding: 18px 16px 15px 12px; 207 | } 208 | 209 | .graphiql-container div .query-editor { 210 | -webkit-box-flex: 1; 211 | -ms-flex: 1; 212 | flex: 1; 213 | position: relative; 214 | } 215 | 216 | .graphiql-container .variable-editor { 217 | display: -webkit-box; 218 | display: -ms-flexbox; 219 | display: flex; 220 | -webkit-box-orient: vertical; 221 | -webkit-box-direction: normal; 222 | -ms-flex-direction: column; 223 | flex-direction: column; 224 | height: 29px; 225 | position: relative; 226 | } 227 | 228 | .graphiql-container .variable-editor-title { 229 | background: #eeeeee; 230 | border-bottom: 1px solid #d6d6d6; 231 | border-top: 1px solid #e0e0e0; 232 | color: #777; 233 | font-variant: small-caps; 234 | font-weight: bold; 235 | letter-spacing: 1px; 236 | line-height: 14px; 237 | padding: 6px 0 8px 43px; 238 | text-transform: lowercase; 239 | -webkit-user-select: none; 240 | -moz-user-select: none; 241 | -ms-user-select: none; 242 | user-select: none; 243 | } 244 | 245 | .graphiql-container .codemirrorWrap { 246 | -webkit-box-flex: 1; 247 | -ms-flex: 1; 248 | flex: 1; 249 | height: 100%; 250 | position: relative; 251 | } 252 | 253 | .graphiql-container .result-window { 254 | -webkit-box-flex: 1; 255 | -ms-flex: 1; 256 | flex: 1; 257 | height: 100%; 258 | position: relative; 259 | } 260 | 261 | .graphiql-container .footer { 262 | background: #f6f7f8; 263 | border-left: 1px solid #e0e0e0; 264 | border-top: 1px solid #e0e0e0; 265 | margin-left: 12px; 266 | position: relative; 267 | } 268 | 269 | .graphiql-container .footer:before { 270 | background: #eeeeee; 271 | bottom: 0; 272 | content: " "; 273 | left: -13px; 274 | position: absolute; 275 | top: -1px; 276 | width: 12px; 277 | } 278 | 279 | /* No `.graphiql-container` here so themes can overwrite */ 280 | .result-window .CodeMirror { 281 | background: #f6f7f8; 282 | } 283 | 284 | .graphiql-container .result-window .CodeMirror-gutters { 285 | background-color: #eeeeee; 286 | border-color: #e0e0e0; 287 | cursor: col-resize; 288 | } 289 | 290 | .graphiql-container .result-window .CodeMirror-foldgutter, 291 | .graphiql-container .result-window .CodeMirror-foldgutter-open:after, 292 | .graphiql-container .result-window .CodeMirror-foldgutter-folded:after { 293 | padding-left: 3px; 294 | } 295 | 296 | .graphiql-container .toolbar-button { 297 | background: #fdfdfd; 298 | background: -webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#ececec)); 299 | background: linear-gradient(#f9f9f9, #ececec); 300 | border-radius: 3px; 301 | -webkit-box-shadow: 302 | inset 0 0 0 1px rgba(0,0,0,0.20), 303 | 0 1px 0 rgba(255,255,255, 0.7), 304 | inset 0 1px #fff; 305 | box-shadow: 306 | inset 0 0 0 1px rgba(0,0,0,0.20), 307 | 0 1px 0 rgba(255,255,255, 0.7), 308 | inset 0 1px #fff; 309 | color: #555; 310 | cursor: pointer; 311 | display: inline-block; 312 | margin: 0 5px; 313 | padding: 3px 11px 5px; 314 | text-decoration: none; 315 | text-overflow: ellipsis; 316 | white-space: nowrap; 317 | max-width: 150px; 318 | } 319 | 320 | .graphiql-container .toolbar-button:active { 321 | background: -webkit-gradient(linear, left top, left bottom, from(#ececec), to(#d5d5d5)); 322 | background: linear-gradient(#ececec, #d5d5d5); 323 | -webkit-box-shadow: 324 | 0 1px 0 rgba(255, 255, 255, 0.7), 325 | inset 0 0 0 1px rgba(0,0,0,0.10), 326 | inset 0 1px 1px 1px rgba(0, 0, 0, 0.12), 327 | inset 0 0 5px rgba(0, 0, 0, 0.1); 328 | box-shadow: 329 | 0 1px 0 rgba(255, 255, 255, 0.7), 330 | inset 0 0 0 1px rgba(0,0,0,0.10), 331 | inset 0 1px 1px 1px rgba(0, 0, 0, 0.12), 332 | inset 0 0 5px rgba(0, 0, 0, 0.1); 333 | } 334 | 335 | .graphiql-container .toolbar-button.error { 336 | background: -webkit-gradient(linear, left top, left bottom, from(#fdf3f3), to(#e6d6d7)); 337 | background: linear-gradient(#fdf3f3, #e6d6d7); 338 | color: #b00; 339 | } 340 | 341 | .graphiql-container .toolbar-button-group { 342 | margin: 0 5px; 343 | white-space: nowrap; 344 | } 345 | 346 | .graphiql-container .toolbar-button-group > * { 347 | margin: 0; 348 | } 349 | 350 | .graphiql-container .toolbar-button-group > *:not(:last-child) { 351 | border-top-right-radius: 0; 352 | border-bottom-right-radius: 0; 353 | } 354 | 355 | .graphiql-container .toolbar-button-group > *:not(:first-child) { 356 | border-top-left-radius: 0; 357 | border-bottom-left-radius: 0; 358 | margin-left: -1px; 359 | } 360 | 361 | .graphiql-container .execute-button-wrap { 362 | height: 34px; 363 | margin: 0 14px 0 28px; 364 | position: relative; 365 | } 366 | 367 | .graphiql-container .execute-button { 368 | background: -webkit-gradient(linear, left top, left bottom, from(#fdfdfd), to(#d2d3d6)); 369 | background: linear-gradient(#fdfdfd, #d2d3d6); 370 | border-radius: 17px; 371 | border: 1px solid rgba(0,0,0,0.25); 372 | -webkit-box-shadow: 0 1px 0 #fff; 373 | box-shadow: 0 1px 0 #fff; 374 | cursor: pointer; 375 | fill: #444; 376 | height: 34px; 377 | margin: 0; 378 | padding: 0; 379 | width: 34px; 380 | } 381 | 382 | .graphiql-container .execute-button svg { 383 | pointer-events: none; 384 | } 385 | 386 | .graphiql-container .execute-button:active { 387 | background: -webkit-gradient(linear, left top, left bottom, from(#e6e6e6), to(#c3c3c3)); 388 | background: linear-gradient(#e6e6e6, #c3c3c3); 389 | -webkit-box-shadow: 390 | 0 1px 0 #fff, 391 | inset 0 0 2px rgba(0, 0, 0, 0.2), 392 | inset 0 0 6px rgba(0, 0, 0, 0.1); 393 | box-shadow: 394 | 0 1px 0 #fff, 395 | inset 0 0 2px rgba(0, 0, 0, 0.2), 396 | inset 0 0 6px rgba(0, 0, 0, 0.1); 397 | } 398 | 399 | .graphiql-container .execute-button:focus { 400 | outline: 0; 401 | } 402 | 403 | .graphiql-container .toolbar-menu, 404 | .graphiql-container .toolbar-select { 405 | position: relative; 406 | } 407 | 408 | .graphiql-container .execute-options, 409 | .graphiql-container .toolbar-menu-items, 410 | .graphiql-container .toolbar-select-options { 411 | background: #fff; 412 | -webkit-box-shadow: 413 | 0 0 0 1px rgba(0,0,0,0.1), 414 | 0 2px 4px rgba(0,0,0,0.25); 415 | box-shadow: 416 | 0 0 0 1px rgba(0,0,0,0.1), 417 | 0 2px 4px rgba(0,0,0,0.25); 418 | margin: 0; 419 | padding: 6px 0; 420 | position: absolute; 421 | z-index: 100; 422 | } 423 | 424 | .graphiql-container .execute-options { 425 | min-width: 100px; 426 | top: 37px; 427 | left: -1px; 428 | } 429 | 430 | .graphiql-container .toolbar-menu-items { 431 | left: 1px; 432 | margin-top: -1px; 433 | min-width: 110%; 434 | top: 100%; 435 | visibility: hidden; 436 | } 437 | 438 | .graphiql-container .toolbar-menu-items.open { 439 | visibility: visible; 440 | } 441 | 442 | .graphiql-container .toolbar-select-options { 443 | left: 0; 444 | min-width: 100%; 445 | top: -5px; 446 | visibility: hidden; 447 | } 448 | 449 | .graphiql-container .toolbar-select-options.open { 450 | visibility: visible; 451 | } 452 | 453 | .graphiql-container .execute-options > li, 454 | .graphiql-container .toolbar-menu-items > li, 455 | .graphiql-container .toolbar-select-options > li { 456 | cursor: pointer; 457 | display: block; 458 | margin: none; 459 | max-width: 300px; 460 | overflow: hidden; 461 | padding: 2px 20px 4px 11px; 462 | text-overflow: ellipsis; 463 | white-space: nowrap; 464 | } 465 | 466 | .graphiql-container .execute-options > li.selected, 467 | .graphiql-container .toolbar-menu-items > li.hover, 468 | .graphiql-container .toolbar-menu-items > li:active, 469 | .graphiql-container .toolbar-menu-items > li:hover, 470 | .graphiql-container .toolbar-select-options > li.hover, 471 | .graphiql-container .toolbar-select-options > li:active, 472 | .graphiql-container .toolbar-select-options > li:hover, 473 | .graphiql-container .history-contents > p:hover, 474 | .graphiql-container .history-contents > p:active { 475 | background: #e10098; 476 | color: #fff; 477 | } 478 | 479 | .graphiql-container .toolbar-select-options > li > svg { 480 | display: inline; 481 | fill: #666; 482 | margin: 0 -6px 0 6px; 483 | pointer-events: none; 484 | vertical-align: middle; 485 | } 486 | 487 | .graphiql-container .toolbar-select-options > li.hover > svg, 488 | .graphiql-container .toolbar-select-options > li:active > svg, 489 | .graphiql-container .toolbar-select-options > li:hover > svg { 490 | fill: #fff; 491 | } 492 | 493 | .graphiql-container .CodeMirror-scroll { 494 | overflow-scrolling: touch; 495 | } 496 | 497 | .graphiql-container .CodeMirror { 498 | color: #141823; 499 | font-family: 500 | 'Consolas', 501 | 'Inconsolata', 502 | 'Droid Sans Mono', 503 | 'Monaco', 504 | monospace; 505 | font-size: 13px; 506 | height: 100%; 507 | left: 0; 508 | position: absolute; 509 | top: 0; 510 | width: 100%; 511 | } 512 | 513 | .graphiql-container .CodeMirror-lines { 514 | padding: 20px 0; 515 | } 516 | 517 | .CodeMirror-hint-information .content { 518 | box-orient: vertical; 519 | color: #141823; 520 | display: -webkit-box; 521 | display: -ms-flexbox; 522 | display: flex; 523 | font-family: system, -apple-system, 'San Francisco', '.SFNSDisplay-Regular', 'Segoe UI', Segoe, 'Segoe WP', 'Helvetica Neue', helvetica, 'Lucida Grande', arial, sans-serif; 524 | font-size: 13px; 525 | line-clamp: 3; 526 | line-height: 16px; 527 | max-height: 48px; 528 | overflow: hidden; 529 | text-overflow: -o-ellipsis-lastline; 530 | } 531 | 532 | .CodeMirror-hint-information .content p:first-child { 533 | margin-top: 0; 534 | } 535 | 536 | .CodeMirror-hint-information .content p:last-child { 537 | margin-bottom: 0; 538 | } 539 | 540 | .CodeMirror-hint-information .infoType { 541 | color: #CA9800; 542 | cursor: pointer; 543 | display: inline; 544 | margin-right: 0.5em; 545 | } 546 | 547 | .autoInsertedLeaf.cm-property { 548 | -webkit-animation-duration: 6s; 549 | animation-duration: 6s; 550 | -webkit-animation-name: insertionFade; 551 | animation-name: insertionFade; 552 | border-bottom: 2px solid rgba(255, 255, 255, 0); 553 | border-radius: 2px; 554 | margin: -2px -4px -1px; 555 | padding: 2px 4px 1px; 556 | } 557 | 558 | @-webkit-keyframes insertionFade { 559 | from, to { 560 | background: rgba(255, 255, 255, 0); 561 | border-color: rgba(255, 255, 255, 0); 562 | } 563 | 564 | 15%, 85% { 565 | background: #fbffc9; 566 | border-color: #f0f3c0; 567 | } 568 | } 569 | 570 | @keyframes insertionFade { 571 | from, to { 572 | background: rgba(255, 255, 255, 0); 573 | border-color: rgba(255, 255, 255, 0); 574 | } 575 | 576 | 15%, 85% { 577 | background: #fbffc9; 578 | border-color: #f0f3c0; 579 | } 580 | } 581 | 582 | div.CodeMirror-lint-tooltip { 583 | background-color: white; 584 | border-radius: 2px; 585 | border: 0; 586 | color: #141823; 587 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 588 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 589 | font-family: 590 | system, 591 | -apple-system, 592 | 'San Francisco', 593 | '.SFNSDisplay-Regular', 594 | 'Segoe UI', 595 | Segoe, 596 | 'Segoe WP', 597 | 'Helvetica Neue', 598 | helvetica, 599 | 'Lucida Grande', 600 | arial, 601 | sans-serif; 602 | font-size: 13px; 603 | line-height: 16px; 604 | max-width: 430px; 605 | opacity: 0; 606 | padding: 8px 10px; 607 | -webkit-transition: opacity 0.15s; 608 | transition: opacity 0.15s; 609 | white-space: pre-wrap; 610 | } 611 | 612 | div.CodeMirror-lint-tooltip > * { 613 | padding-left: 23px; 614 | } 615 | 616 | div.CodeMirror-lint-tooltip > * + * { 617 | margin-top: 12px; 618 | } 619 | 620 | /* COLORS */ 621 | 622 | .graphiql-container .CodeMirror-foldmarker { 623 | border-radius: 4px; 624 | background: #08f; 625 | background: -webkit-gradient(linear, left top, left bottom, from(#43A8FF), to(#0F83E8)); 626 | background: linear-gradient(#43A8FF, #0F83E8); 627 | -webkit-box-shadow: 628 | 0 1px 1px rgba(0, 0, 0, 0.2), 629 | inset 0 0 0 1px rgba(0, 0, 0, 0.1); 630 | box-shadow: 631 | 0 1px 1px rgba(0, 0, 0, 0.2), 632 | inset 0 0 0 1px rgba(0, 0, 0, 0.1); 633 | color: white; 634 | font-family: arial; 635 | font-size: 12px; 636 | line-height: 0; 637 | margin: 0 3px; 638 | padding: 0px 4px 1px; 639 | text-shadow: 0 -1px rgba(0, 0, 0, 0.1); 640 | } 641 | 642 | .graphiql-container div.CodeMirror span.CodeMirror-matchingbracket { 643 | color: #555; 644 | text-decoration: underline; 645 | } 646 | 647 | .graphiql-container div.CodeMirror span.CodeMirror-nonmatchingbracket { 648 | color: #f00; 649 | } 650 | 651 | /* Comment */ 652 | .cm-comment { 653 | color: #999; 654 | } 655 | 656 | /* Punctuation */ 657 | .cm-punctuation { 658 | color: #555; 659 | } 660 | 661 | /* Keyword */ 662 | .cm-keyword { 663 | color: #B11A04; 664 | } 665 | 666 | /* OperationName, FragmentName */ 667 | .cm-def { 668 | color: #D2054E; 669 | } 670 | 671 | /* FieldName */ 672 | .cm-property { 673 | color: #1F61A0; 674 | } 675 | 676 | /* FieldAlias */ 677 | .cm-qualifier { 678 | color: #1C92A9; 679 | } 680 | 681 | /* ArgumentName and ObjectFieldName */ 682 | .cm-attribute { 683 | color: #8B2BB9; 684 | } 685 | 686 | /* Number */ 687 | .cm-number { 688 | color: #2882F9; 689 | } 690 | 691 | /* String */ 692 | .cm-string { 693 | color: #D64292; 694 | } 695 | 696 | /* Boolean */ 697 | .cm-builtin { 698 | color: #D47509; 699 | } 700 | 701 | /* EnumValue */ 702 | .cm-string-2 { 703 | color: #0B7FC7; 704 | } 705 | 706 | /* Variable */ 707 | .cm-variable { 708 | color: #397D13; 709 | } 710 | 711 | /* Directive */ 712 | .cm-meta { 713 | color: #B33086; 714 | } 715 | 716 | /* Type */ 717 | .cm-atom { 718 | color: #CA9800; 719 | } 720 | /* BASICS */ 721 | 722 | .CodeMirror { 723 | /* Set height, width, borders, and global font properties here */ 724 | color: black; 725 | font-family: monospace; 726 | height: 300px; 727 | } 728 | 729 | /* PADDING */ 730 | 731 | .CodeMirror-lines { 732 | padding: 4px 0; /* Vertical padding around content */ 733 | } 734 | .CodeMirror pre { 735 | padding: 0 4px; /* Horizontal padding of content */ 736 | } 737 | 738 | .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 739 | background-color: white; /* The little square between H and V scrollbars */ 740 | } 741 | 742 | /* GUTTER */ 743 | 744 | .CodeMirror-gutters { 745 | border-right: 1px solid #ddd; 746 | background-color: #f7f7f7; 747 | white-space: nowrap; 748 | } 749 | .CodeMirror-linenumbers {} 750 | .CodeMirror-linenumber { 751 | color: #999; 752 | min-width: 20px; 753 | padding: 0 3px 0 5px; 754 | text-align: right; 755 | white-space: nowrap; 756 | } 757 | 758 | .CodeMirror-guttermarker { color: black; } 759 | .CodeMirror-guttermarker-subtle { color: #999; } 760 | 761 | /* CURSOR */ 762 | 763 | .CodeMirror .CodeMirror-cursor { 764 | border-left: 1px solid black; 765 | } 766 | /* Shown when moving in bi-directional text */ 767 | .CodeMirror div.CodeMirror-secondarycursor { 768 | border-left: 1px solid silver; 769 | } 770 | .CodeMirror.cm-fat-cursor div.CodeMirror-cursor { 771 | background: #7e7; 772 | border: 0; 773 | width: auto; 774 | } 775 | .CodeMirror.cm-fat-cursor div.CodeMirror-cursors { 776 | z-index: 1; 777 | } 778 | 779 | .cm-animate-fat-cursor { 780 | -webkit-animation: blink 1.06s steps(1) infinite; 781 | animation: blink 1.06s steps(1) infinite; 782 | border: 0; 783 | width: auto; 784 | } 785 | @-webkit-keyframes blink { 786 | 0% { background: #7e7; } 787 | 50% { background: none; } 788 | 100% { background: #7e7; } 789 | } 790 | @keyframes blink { 791 | 0% { background: #7e7; } 792 | 50% { background: none; } 793 | 100% { background: #7e7; } 794 | } 795 | 796 | /* Can style cursor different in overwrite (non-insert) mode */ 797 | div.CodeMirror-overwrite div.CodeMirror-cursor {} 798 | 799 | .cm-tab { display: inline-block; text-decoration: inherit; } 800 | 801 | .CodeMirror-ruler { 802 | border-left: 1px solid #ccc; 803 | position: absolute; 804 | } 805 | 806 | /* DEFAULT THEME */ 807 | 808 | .cm-s-default .cm-keyword {color: #708;} 809 | .cm-s-default .cm-atom {color: #219;} 810 | .cm-s-default .cm-number {color: #164;} 811 | .cm-s-default .cm-def {color: #00f;} 812 | .cm-s-default .cm-variable, 813 | .cm-s-default .cm-punctuation, 814 | .cm-s-default .cm-property, 815 | .cm-s-default .cm-operator {} 816 | .cm-s-default .cm-variable-2 {color: #05a;} 817 | .cm-s-default .cm-variable-3 {color: #085;} 818 | .cm-s-default .cm-comment {color: #a50;} 819 | .cm-s-default .cm-string {color: #a11;} 820 | .cm-s-default .cm-string-2 {color: #f50;} 821 | .cm-s-default .cm-meta {color: #555;} 822 | .cm-s-default .cm-qualifier {color: #555;} 823 | .cm-s-default .cm-builtin {color: #30a;} 824 | .cm-s-default .cm-bracket {color: #997;} 825 | .cm-s-default .cm-tag {color: #170;} 826 | .cm-s-default .cm-attribute {color: #00c;} 827 | .cm-s-default .cm-header {color: blue;} 828 | .cm-s-default .cm-quote {color: #090;} 829 | .cm-s-default .cm-hr {color: #999;} 830 | .cm-s-default .cm-link {color: #00c;} 831 | 832 | .cm-negative {color: #d44;} 833 | .cm-positive {color: #292;} 834 | .cm-header, .cm-strong {font-weight: bold;} 835 | .cm-em {font-style: italic;} 836 | .cm-link {text-decoration: underline;} 837 | .cm-strikethrough {text-decoration: line-through;} 838 | 839 | .cm-s-default .cm-error {color: #f00;} 840 | .cm-invalidchar {color: #f00;} 841 | 842 | .CodeMirror-composing { border-bottom: 2px solid; } 843 | 844 | /* Default styles for common addons */ 845 | 846 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} 847 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} 848 | .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } 849 | .CodeMirror-activeline-background {background: #e8f2ff;} 850 | 851 | /* STOP */ 852 | 853 | /* The rest of this file contains styles related to the mechanics of 854 | the editor. You probably shouldn't touch them. */ 855 | 856 | .CodeMirror { 857 | background: white; 858 | overflow: hidden; 859 | position: relative; 860 | } 861 | 862 | .CodeMirror-scroll { 863 | height: 100%; 864 | /* 30px is the magic margin used to hide the element's real scrollbars */ 865 | /* See overflow: hidden in .CodeMirror */ 866 | margin-bottom: -30px; margin-right: -30px; 867 | outline: none; /* Prevent dragging from highlighting the element */ 868 | overflow: scroll !important; /* Things will break if this is overridden */ 869 | padding-bottom: 30px; 870 | position: relative; 871 | } 872 | .CodeMirror-sizer { 873 | border-right: 30px solid transparent; 874 | position: relative; 875 | } 876 | 877 | /* The fake, visible scrollbars. Used to force redraw during scrolling 878 | before actual scrolling happens, thus preventing shaking and 879 | flickering artifacts. */ 880 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 881 | display: none; 882 | position: absolute; 883 | z-index: 6; 884 | } 885 | .CodeMirror-vscrollbar { 886 | overflow-x: hidden; 887 | overflow-y: scroll; 888 | right: 0; top: 0; 889 | } 890 | .CodeMirror-hscrollbar { 891 | bottom: 0; left: 0; 892 | overflow-x: scroll; 893 | overflow-y: hidden; 894 | } 895 | .CodeMirror-scrollbar-filler { 896 | right: 0; bottom: 0; 897 | } 898 | .CodeMirror-gutter-filler { 899 | left: 0; bottom: 0; 900 | } 901 | 902 | .CodeMirror-gutters { 903 | min-height: 100%; 904 | position: absolute; left: 0; top: 0; 905 | z-index: 3; 906 | } 907 | .CodeMirror-gutter { 908 | display: inline-block; 909 | height: 100%; 910 | margin-bottom: -30px; 911 | vertical-align: top; 912 | white-space: normal; 913 | /* Hack to make IE7 behave */ 914 | *zoom:1; 915 | *display:inline; 916 | } 917 | .CodeMirror-gutter-wrapper { 918 | background: none !important; 919 | border: none !important; 920 | position: absolute; 921 | z-index: 4; 922 | } 923 | .CodeMirror-gutter-background { 924 | position: absolute; 925 | top: 0; bottom: 0; 926 | z-index: 4; 927 | } 928 | .CodeMirror-gutter-elt { 929 | cursor: default; 930 | position: absolute; 931 | z-index: 4; 932 | } 933 | .CodeMirror-gutter-wrapper { 934 | -webkit-user-select: none; 935 | -moz-user-select: none; 936 | -ms-user-select: none; 937 | user-select: none; 938 | } 939 | 940 | .CodeMirror-lines { 941 | cursor: text; 942 | min-height: 1px; /* prevents collapsing before first draw */ 943 | } 944 | .CodeMirror pre { 945 | -webkit-tap-highlight-color: transparent; 946 | /* Reset some styles that the rest of the page might have set */ 947 | background: transparent; 948 | border-radius: 0; 949 | border-width: 0; 950 | color: inherit; 951 | font-family: inherit; 952 | font-size: inherit; 953 | -webkit-font-variant-ligatures: none; 954 | font-variant-ligatures: none; 955 | line-height: inherit; 956 | margin: 0; 957 | overflow: visible; 958 | position: relative; 959 | white-space: pre; 960 | word-wrap: normal; 961 | z-index: 2; 962 | } 963 | .CodeMirror-wrap pre { 964 | word-wrap: break-word; 965 | white-space: pre-wrap; 966 | word-break: normal; 967 | } 968 | 969 | .CodeMirror-linebackground { 970 | position: absolute; 971 | left: 0; right: 0; top: 0; bottom: 0; 972 | z-index: 0; 973 | } 974 | 975 | .CodeMirror-linewidget { 976 | overflow: auto; 977 | position: relative; 978 | z-index: 2; 979 | } 980 | 981 | .CodeMirror-widget {} 982 | 983 | .CodeMirror-code { 984 | outline: none; 985 | } 986 | 987 | /* Force content-box sizing for the elements where we expect it */ 988 | .CodeMirror-scroll, 989 | .CodeMirror-sizer, 990 | .CodeMirror-gutter, 991 | .CodeMirror-gutters, 992 | .CodeMirror-linenumber { 993 | -webkit-box-sizing: content-box; 994 | box-sizing: content-box; 995 | } 996 | 997 | .CodeMirror-measure { 998 | height: 0; 999 | overflow: hidden; 1000 | position: absolute; 1001 | visibility: hidden; 1002 | width: 100%; 1003 | } 1004 | 1005 | .CodeMirror-cursor { position: absolute; } 1006 | .CodeMirror-measure pre { position: static; } 1007 | 1008 | div.CodeMirror-cursors { 1009 | position: relative; 1010 | visibility: hidden; 1011 | z-index: 3; 1012 | } 1013 | div.CodeMirror-dragcursors { 1014 | visibility: visible; 1015 | } 1016 | 1017 | .CodeMirror-focused div.CodeMirror-cursors { 1018 | visibility: visible; 1019 | } 1020 | 1021 | .CodeMirror-selected { background: #d9d9d9; } 1022 | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } 1023 | .CodeMirror-crosshair { cursor: crosshair; } 1024 | .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } 1025 | .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } 1026 | .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } 1027 | 1028 | .cm-searching { 1029 | background: #ffa; 1030 | background: rgba(255, 255, 0, .4); 1031 | } 1032 | 1033 | /* IE7 hack to prevent it from returning funny offsetTops on the spans */ 1034 | .CodeMirror span { *vertical-align: text-bottom; } 1035 | 1036 | /* Used to force a border model for a node */ 1037 | .cm-force-border { padding-right: .1px; } 1038 | 1039 | @media print { 1040 | /* Hide the cursor when printing */ 1041 | .CodeMirror div.CodeMirror-cursors { 1042 | visibility: hidden; 1043 | } 1044 | } 1045 | 1046 | /* See issue #2901 */ 1047 | .cm-tab-wrap-hack:after { content: ''; } 1048 | 1049 | /* Help users use markselection to safely style text background */ 1050 | span.CodeMirror-selectedtext { background: none; } 1051 | 1052 | .CodeMirror-dialog { 1053 | background: inherit; 1054 | color: inherit; 1055 | left: 0; right: 0; 1056 | overflow: hidden; 1057 | padding: .1em .8em; 1058 | position: absolute; 1059 | z-index: 15; 1060 | } 1061 | 1062 | .CodeMirror-dialog-top { 1063 | border-bottom: 1px solid #eee; 1064 | top: 0; 1065 | } 1066 | 1067 | .CodeMirror-dialog-bottom { 1068 | border-top: 1px solid #eee; 1069 | bottom: 0; 1070 | } 1071 | 1072 | .CodeMirror-dialog input { 1073 | background: transparent; 1074 | border: 1px solid #d3d6db; 1075 | color: inherit; 1076 | font-family: monospace; 1077 | outline: none; 1078 | width: 20em; 1079 | } 1080 | 1081 | .CodeMirror-dialog button { 1082 | font-size: 70%; 1083 | } 1084 | .graphiql-container .doc-explorer { 1085 | background: white; 1086 | } 1087 | 1088 | .graphiql-container .doc-explorer-title-bar, 1089 | .graphiql-container .history-title-bar { 1090 | cursor: default; 1091 | display: -webkit-box; 1092 | display: -ms-flexbox; 1093 | display: flex; 1094 | height: 34px; 1095 | line-height: 14px; 1096 | padding: 8px 8px 5px; 1097 | position: relative; 1098 | -webkit-user-select: none; 1099 | -moz-user-select: none; 1100 | -ms-user-select: none; 1101 | user-select: none; 1102 | } 1103 | 1104 | .graphiql-container .doc-explorer-title, 1105 | .graphiql-container .history-title { 1106 | -webkit-box-flex: 1; 1107 | -ms-flex: 1; 1108 | flex: 1; 1109 | font-weight: bold; 1110 | overflow-x: hidden; 1111 | padding: 10px 0 10px 10px; 1112 | text-align: center; 1113 | text-overflow: ellipsis; 1114 | -webkit-user-select: initial; 1115 | -moz-user-select: initial; 1116 | -ms-user-select: initial; 1117 | user-select: initial; 1118 | white-space: nowrap; 1119 | } 1120 | 1121 | .graphiql-container .doc-explorer-back { 1122 | color: #3B5998; 1123 | cursor: pointer; 1124 | margin: -7px 0 -6px -8px; 1125 | overflow-x: hidden; 1126 | padding: 17px 12px 16px 16px; 1127 | text-overflow: ellipsis; 1128 | white-space: nowrap; 1129 | } 1130 | 1131 | .doc-explorer-narrow .doc-explorer-back { 1132 | width: 0; 1133 | } 1134 | 1135 | .graphiql-container .doc-explorer-back:before { 1136 | border-left: 2px solid #3B5998; 1137 | border-top: 2px solid #3B5998; 1138 | content: ''; 1139 | display: inline-block; 1140 | height: 9px; 1141 | margin: 0 3px -1px 0; 1142 | position: relative; 1143 | -webkit-transform: rotate(-45deg); 1144 | transform: rotate(-45deg); 1145 | width: 9px; 1146 | } 1147 | 1148 | .graphiql-container .doc-explorer-rhs { 1149 | position: relative; 1150 | } 1151 | 1152 | .graphiql-container .doc-explorer-contents, 1153 | .graphiql-container .history-contents { 1154 | background-color: #ffffff; 1155 | border-top: 1px solid #d6d6d6; 1156 | bottom: 0; 1157 | left: 0; 1158 | overflow-y: auto; 1159 | padding: 20px 15px; 1160 | position: absolute; 1161 | right: 0; 1162 | top: 47px; 1163 | } 1164 | 1165 | .graphiql-container .doc-explorer-contents { 1166 | min-width: 300px; 1167 | } 1168 | 1169 | .graphiql-container .doc-type-description p:first-child , 1170 | .graphiql-container .doc-type-description blockquote:first-child { 1171 | margin-top: 0; 1172 | } 1173 | 1174 | .graphiql-container .doc-explorer-contents a { 1175 | cursor: pointer; 1176 | text-decoration: none; 1177 | } 1178 | 1179 | .graphiql-container .doc-explorer-contents a:hover { 1180 | text-decoration: underline; 1181 | } 1182 | 1183 | .graphiql-container .doc-value-description > :first-child { 1184 | margin-top: 4px; 1185 | } 1186 | 1187 | .graphiql-container .doc-value-description > :last-child { 1188 | margin-bottom: 4px; 1189 | } 1190 | 1191 | .graphiql-container .doc-category { 1192 | margin: 20px 0; 1193 | } 1194 | 1195 | .graphiql-container .doc-category-title { 1196 | border-bottom: 1px solid #e0e0e0; 1197 | color: #777; 1198 | cursor: default; 1199 | font-size: 14px; 1200 | font-variant: small-caps; 1201 | font-weight: bold; 1202 | letter-spacing: 1px; 1203 | margin: 0 -15px 10px 0; 1204 | padding: 10px 0; 1205 | -webkit-user-select: none; 1206 | -moz-user-select: none; 1207 | -ms-user-select: none; 1208 | user-select: none; 1209 | } 1210 | 1211 | .graphiql-container .doc-category-item { 1212 | margin: 12px 0; 1213 | color: #555; 1214 | } 1215 | 1216 | .graphiql-container .keyword { 1217 | color: #B11A04; 1218 | } 1219 | 1220 | .graphiql-container .type-name { 1221 | color: #CA9800; 1222 | } 1223 | 1224 | .graphiql-container .field-name { 1225 | color: #1F61A0; 1226 | } 1227 | 1228 | .graphiql-container .field-short-description { 1229 | color: #999; 1230 | margin-left: 5px; 1231 | overflow: hidden; 1232 | text-overflow: ellipsis; 1233 | white-space: nowrap; 1234 | } 1235 | 1236 | .graphiql-container .enum-value { 1237 | color: #0B7FC7; 1238 | } 1239 | 1240 | .graphiql-container .arg-name { 1241 | color: #8B2BB9; 1242 | } 1243 | 1244 | .graphiql-container .arg { 1245 | display: block; 1246 | margin-left: 1em; 1247 | } 1248 | 1249 | .graphiql-container .arg:first-child:last-child, 1250 | .graphiql-container .arg:first-child:nth-last-child(2), 1251 | .graphiql-container .arg:first-child:nth-last-child(2) ~ .arg { 1252 | display: inherit; 1253 | margin: inherit; 1254 | } 1255 | 1256 | .graphiql-container .arg:first-child:nth-last-child(2):after { 1257 | content: ', '; 1258 | } 1259 | 1260 | .graphiql-container .arg-default-value { 1261 | color: #0B7FC7; 1262 | } 1263 | 1264 | .graphiql-container .doc-deprecation { 1265 | background: #fffae8; 1266 | -webkit-box-shadow: inset 0 0 1px #bfb063; 1267 | box-shadow: inset 0 0 1px #bfb063; 1268 | color: #867F70; 1269 | line-height: 16px; 1270 | margin: 8px -8px; 1271 | max-height: 80px; 1272 | overflow: hidden; 1273 | padding: 8px; 1274 | border-radius: 3px; 1275 | } 1276 | 1277 | .graphiql-container .doc-deprecation:before { 1278 | content: 'Deprecated:'; 1279 | color: #c79b2e; 1280 | cursor: default; 1281 | display: block; 1282 | font-size: 9px; 1283 | font-weight: bold; 1284 | letter-spacing: 1px; 1285 | line-height: 1; 1286 | padding-bottom: 5px; 1287 | text-transform: uppercase; 1288 | -webkit-user-select: none; 1289 | -moz-user-select: none; 1290 | -ms-user-select: none; 1291 | user-select: none; 1292 | } 1293 | 1294 | .graphiql-container .doc-deprecation > :first-child { 1295 | margin-top: 0; 1296 | } 1297 | 1298 | .graphiql-container .doc-deprecation > :last-child { 1299 | margin-bottom: 0; 1300 | } 1301 | 1302 | .graphiql-container .show-btn { 1303 | -webkit-appearance: initial; 1304 | display: block; 1305 | border-radius: 3px; 1306 | border: solid 1px #ccc; 1307 | text-align: center; 1308 | padding: 8px 12px 10px; 1309 | width: 100%; 1310 | -webkit-box-sizing: border-box; 1311 | box-sizing: border-box; 1312 | background: #fbfcfc; 1313 | color: #555; 1314 | cursor: pointer; 1315 | } 1316 | 1317 | .graphiql-container .search-box { 1318 | border-bottom: 1px solid #d3d6db; 1319 | display: block; 1320 | font-size: 14px; 1321 | margin: -15px -15px 12px 0; 1322 | position: relative; 1323 | } 1324 | 1325 | .graphiql-container .search-box:before { 1326 | content: '\26b2'; 1327 | cursor: pointer; 1328 | display: block; 1329 | font-size: 24px; 1330 | position: absolute; 1331 | top: -2px; 1332 | -webkit-transform: rotate(-45deg); 1333 | transform: rotate(-45deg); 1334 | -webkit-user-select: none; 1335 | -moz-user-select: none; 1336 | -ms-user-select: none; 1337 | user-select: none; 1338 | } 1339 | 1340 | .graphiql-container .search-box .search-box-clear { 1341 | background-color: #d0d0d0; 1342 | border-radius: 12px; 1343 | color: #fff; 1344 | cursor: pointer; 1345 | font-size: 11px; 1346 | padding: 1px 5px 2px; 1347 | position: absolute; 1348 | right: 3px; 1349 | top: 8px; 1350 | -webkit-user-select: none; 1351 | -moz-user-select: none; 1352 | -ms-user-select: none; 1353 | user-select: none; 1354 | } 1355 | 1356 | .graphiql-container .search-box .search-box-clear:hover { 1357 | background-color: #b9b9b9; 1358 | } 1359 | 1360 | .graphiql-container .search-box > input { 1361 | border: none; 1362 | -webkit-box-sizing: border-box; 1363 | box-sizing: border-box; 1364 | font-size: 14px; 1365 | outline: none; 1366 | padding: 6px 24px 8px 20px; 1367 | width: 100%; 1368 | } 1369 | 1370 | .graphiql-container .error-container { 1371 | font-weight: bold; 1372 | left: 0; 1373 | letter-spacing: 1px; 1374 | opacity: 0.5; 1375 | position: absolute; 1376 | right: 0; 1377 | text-align: center; 1378 | text-transform: uppercase; 1379 | top: 50%; 1380 | -webkit-transform: translate(0, -50%); 1381 | transform: translate(0, -50%); 1382 | } 1383 | .CodeMirror-foldmarker { 1384 | color: blue; 1385 | cursor: pointer; 1386 | font-family: arial; 1387 | line-height: .3; 1388 | text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px; 1389 | } 1390 | .CodeMirror-foldgutter { 1391 | width: .7em; 1392 | } 1393 | .CodeMirror-foldgutter-open, 1394 | .CodeMirror-foldgutter-folded { 1395 | cursor: pointer; 1396 | } 1397 | .CodeMirror-foldgutter-open:after { 1398 | content: "\25BE"; 1399 | } 1400 | .CodeMirror-foldgutter-folded:after { 1401 | content: "\25B8"; 1402 | } 1403 | .graphiql-container .history-contents { 1404 | font-family: 'Consolas', 'Inconsolata', 'Droid Sans Mono', 'Monaco', monospace; 1405 | padding: 0; 1406 | } 1407 | 1408 | .graphiql-container .history-contents p { 1409 | font-size: 12px; 1410 | overflow: hidden; 1411 | text-overflow: ellipsis; 1412 | white-space: nowrap; 1413 | margin: 0; 1414 | padding: 8px; 1415 | border-bottom: 1px solid #e0e0e0; 1416 | } 1417 | 1418 | .graphiql-container .history-contents p:hover { 1419 | cursor: pointer; 1420 | } 1421 | .CodeMirror-info { 1422 | background: white; 1423 | border-radius: 2px; 1424 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 1425 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 1426 | -webkit-box-sizing: border-box; 1427 | box-sizing: border-box; 1428 | color: #555; 1429 | font-family: 1430 | system, 1431 | -apple-system, 1432 | 'San Francisco', 1433 | '.SFNSDisplay-Regular', 1434 | 'Segoe UI', 1435 | Segoe, 1436 | 'Segoe WP', 1437 | 'Helvetica Neue', 1438 | helvetica, 1439 | 'Lucida Grande', 1440 | arial, 1441 | sans-serif; 1442 | font-size: 13px; 1443 | line-height: 16px; 1444 | margin: 8px -8px; 1445 | max-width: 400px; 1446 | opacity: 0; 1447 | overflow: hidden; 1448 | padding: 8px 8px; 1449 | position: fixed; 1450 | -webkit-transition: opacity 0.15s; 1451 | transition: opacity 0.15s; 1452 | z-index: 50; 1453 | } 1454 | 1455 | .CodeMirror-info :first-child { 1456 | margin-top: 0; 1457 | } 1458 | 1459 | .CodeMirror-info :last-child { 1460 | margin-bottom: 0; 1461 | } 1462 | 1463 | .CodeMirror-info p { 1464 | margin: 1em 0; 1465 | } 1466 | 1467 | .CodeMirror-info .info-description { 1468 | color: #777; 1469 | line-height: 16px; 1470 | margin-top: 1em; 1471 | max-height: 80px; 1472 | overflow: hidden; 1473 | } 1474 | 1475 | .CodeMirror-info .info-deprecation { 1476 | background: #fffae8; 1477 | -webkit-box-shadow: inset 0 1px 1px -1px #bfb063; 1478 | box-shadow: inset 0 1px 1px -1px #bfb063; 1479 | color: #867F70; 1480 | line-height: 16px; 1481 | margin: -8px; 1482 | margin-top: 8px; 1483 | max-height: 80px; 1484 | overflow: hidden; 1485 | padding: 8px; 1486 | } 1487 | 1488 | .CodeMirror-info .info-deprecation-label { 1489 | color: #c79b2e; 1490 | cursor: default; 1491 | display: block; 1492 | font-size: 9px; 1493 | font-weight: bold; 1494 | letter-spacing: 1px; 1495 | line-height: 1; 1496 | padding-bottom: 5px; 1497 | text-transform: uppercase; 1498 | -webkit-user-select: none; 1499 | -moz-user-select: none; 1500 | -ms-user-select: none; 1501 | user-select: none; 1502 | } 1503 | 1504 | .CodeMirror-info .info-deprecation-label + * { 1505 | margin-top: 0; 1506 | } 1507 | 1508 | .CodeMirror-info a { 1509 | text-decoration: none; 1510 | } 1511 | 1512 | .CodeMirror-info a:hover { 1513 | text-decoration: underline; 1514 | } 1515 | 1516 | .CodeMirror-info .type-name { 1517 | color: #CA9800; 1518 | } 1519 | 1520 | .CodeMirror-info .field-name { 1521 | color: #1F61A0; 1522 | } 1523 | 1524 | .CodeMirror-info .enum-value { 1525 | color: #0B7FC7; 1526 | } 1527 | 1528 | .CodeMirror-info .arg-name { 1529 | color: #8B2BB9; 1530 | } 1531 | 1532 | .CodeMirror-info .directive-name { 1533 | color: #B33086; 1534 | } 1535 | .CodeMirror-jump-token { 1536 | text-decoration: underline; 1537 | cursor: pointer; 1538 | } 1539 | /* The lint marker gutter */ 1540 | .CodeMirror-lint-markers { 1541 | width: 16px; 1542 | } 1543 | 1544 | .CodeMirror-lint-tooltip { 1545 | background-color: infobackground; 1546 | border-radius: 4px 4px 4px 4px; 1547 | border: 1px solid black; 1548 | color: infotext; 1549 | font-family: monospace; 1550 | font-size: 10pt; 1551 | max-width: 600px; 1552 | opacity: 0; 1553 | overflow: hidden; 1554 | padding: 2px 5px; 1555 | position: fixed; 1556 | -webkit-transition: opacity .4s; 1557 | transition: opacity .4s; 1558 | white-space: pre-wrap; 1559 | z-index: 100; 1560 | } 1561 | 1562 | .CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning { 1563 | background-position: left bottom; 1564 | background-repeat: repeat-x; 1565 | } 1566 | 1567 | .CodeMirror-lint-mark-error { 1568 | background-image: 1569 | url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==") 1570 | ; 1571 | } 1572 | 1573 | .CodeMirror-lint-mark-warning { 1574 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII="); 1575 | } 1576 | 1577 | .CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning { 1578 | background-position: center center; 1579 | background-repeat: no-repeat; 1580 | cursor: pointer; 1581 | display: inline-block; 1582 | height: 16px; 1583 | position: relative; 1584 | vertical-align: middle; 1585 | width: 16px; 1586 | } 1587 | 1588 | .CodeMirror-lint-message-error, .CodeMirror-lint-message-warning { 1589 | background-position: top left; 1590 | background-repeat: no-repeat; 1591 | padding-left: 18px; 1592 | } 1593 | 1594 | .CodeMirror-lint-marker-error, .CodeMirror-lint-message-error { 1595 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII="); 1596 | } 1597 | 1598 | .CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning { 1599 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII="); 1600 | } 1601 | 1602 | .CodeMirror-lint-marker-multiple { 1603 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC"); 1604 | background-position: right bottom; 1605 | background-repeat: no-repeat; 1606 | width: 100%; height: 100%; 1607 | } 1608 | .graphiql-container .spinner-container { 1609 | height: 36px; 1610 | left: 50%; 1611 | position: absolute; 1612 | top: 50%; 1613 | -webkit-transform: translate(-50%, -50%); 1614 | transform: translate(-50%, -50%); 1615 | width: 36px; 1616 | z-index: 10; 1617 | } 1618 | 1619 | .graphiql-container .spinner { 1620 | -webkit-animation: rotation .6s infinite linear; 1621 | animation: rotation .6s infinite linear; 1622 | border-bottom: 6px solid rgba(150, 150, 150, .15); 1623 | border-left: 6px solid rgba(150, 150, 150, .15); 1624 | border-radius: 100%; 1625 | border-right: 6px solid rgba(150, 150, 150, .15); 1626 | border-top: 6px solid rgba(150, 150, 150, .8); 1627 | display: inline-block; 1628 | height: 24px; 1629 | position: absolute; 1630 | vertical-align: middle; 1631 | width: 24px; 1632 | } 1633 | 1634 | @-webkit-keyframes rotation { 1635 | from { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 1636 | to { -webkit-transform: rotate(359deg); transform: rotate(359deg); } 1637 | } 1638 | 1639 | @keyframes rotation { 1640 | from { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 1641 | to { -webkit-transform: rotate(359deg); transform: rotate(359deg); } 1642 | } 1643 | .CodeMirror-hints { 1644 | background: white; 1645 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 1646 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); 1647 | font-family: 'Consolas', 'Inconsolata', 'Droid Sans Mono', 'Monaco', monospace; 1648 | font-size: 13px; 1649 | list-style: none; 1650 | margin-left: -6px; 1651 | margin: 0; 1652 | max-height: 14.5em; 1653 | overflow-y: auto; 1654 | overflow: hidden; 1655 | padding: 0; 1656 | position: absolute; 1657 | z-index: 10; 1658 | } 1659 | 1660 | .CodeMirror-hint { 1661 | border-top: solid 1px #f7f7f7; 1662 | color: #141823; 1663 | cursor: pointer; 1664 | margin: 0; 1665 | max-width: 300px; 1666 | overflow: hidden; 1667 | padding: 2px 6px; 1668 | white-space: pre; 1669 | } 1670 | 1671 | li.CodeMirror-hint-active { 1672 | background-color: #08f; 1673 | border-top-color: white; 1674 | color: white; 1675 | } 1676 | 1677 | .CodeMirror-hint-information { 1678 | border-top: solid 1px #c0c0c0; 1679 | max-width: 300px; 1680 | padding: 4px 6px; 1681 | position: relative; 1682 | z-index: 1; 1683 | } 1684 | 1685 | .CodeMirror-hint-information:first-child { 1686 | border-bottom: solid 1px #c0c0c0; 1687 | border-top: none; 1688 | margin-bottom: -1px; 1689 | } 1690 | 1691 | .CodeMirror-hint-deprecation { 1692 | background: #fffae8; 1693 | -webkit-box-shadow: inset 0 1px 1px -1px #bfb063; 1694 | box-shadow: inset 0 1px 1px -1px #bfb063; 1695 | color: #867F70; 1696 | font-family: 1697 | system, 1698 | -apple-system, 1699 | 'San Francisco', 1700 | '.SFNSDisplay-Regular', 1701 | 'Segoe UI', 1702 | Segoe, 1703 | 'Segoe WP', 1704 | 'Helvetica Neue', 1705 | helvetica, 1706 | 'Lucida Grande', 1707 | arial, 1708 | sans-serif; 1709 | font-size: 13px; 1710 | line-height: 16px; 1711 | margin-top: 4px; 1712 | max-height: 80px; 1713 | overflow: hidden; 1714 | padding: 6px; 1715 | } 1716 | 1717 | .CodeMirror-hint-deprecation .deprecation-label { 1718 | color: #c79b2e; 1719 | cursor: default; 1720 | display: block; 1721 | font-size: 9px; 1722 | font-weight: bold; 1723 | letter-spacing: 1px; 1724 | line-height: 1; 1725 | padding-bottom: 5px; 1726 | text-transform: uppercase; 1727 | -webkit-user-select: none; 1728 | -moz-user-select: none; 1729 | -ms-user-select: none; 1730 | user-select: none; 1731 | } 1732 | 1733 | .CodeMirror-hint-deprecation .deprecation-label + * { 1734 | margin-top: 0; 1735 | } 1736 | 1737 | .CodeMirror-hint-deprecation :last-child { 1738 | margin-bottom: 0; 1739 | } 1740 | -------------------------------------------------------------------------------- /Server/wwwroot/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
Loading...
49 | 160 | 161 | 162 | --------------------------------------------------------------------------------