├── .editorconfig ├── .github ├── FUNDING.yml └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── Directory.Build.props ├── LICENSE.md ├── NetlifySharp.sln ├── README.md ├── RELEASE.md ├── build.cmd ├── icon.png ├── marvin.cmd ├── marvin.yml ├── src └── NetlifySharp │ ├── ClientModelCreationConverter.cs │ ├── HttpClientWrapper.cs │ ├── IClientModel.cs │ ├── NetlifyClient.Generated.cs │ ├── NetlifyClient.cs │ ├── NetlifyException.cs │ ├── NetlifySharp.csproj │ └── Site.cs ├── stylecop.json ├── tests.ruleset └── tools └── NetlifySharp.Generator ├── CamelCaseParameterNameGenerator.cs ├── ClassBodyTemplate.cs ├── ClassConstructorTemplate.cs ├── ClassInheritanceTemplate.cs ├── CustomTemplateFactory.cs ├── NetlifySharp.Generator.csproj ├── PascalCasePropertyNameGenerator.cs └── Program.cs /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome:http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Don't use tabs for indentation. 7 | [*] 8 | indent_style = space 9 | # (Please don't specify an indent_size here; that has too many unintended consequences.) 10 | 11 | # Code files 12 | [*.{cs,csx,vb,vbx}] 13 | indent_size = 4 14 | 15 | # Xml project files 16 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] 17 | indent_size = 2 18 | 19 | # Xml config files 20 | [*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] 21 | indent_size = 2 22 | 23 | # JSON files 24 | [*.json] 25 | indent_size = 2 26 | 27 | # Dotnet code style settings: 28 | [*.{cs,vb}] 29 | # Sort using and Import directives with System.* appearing first 30 | dotnet_sort_system_directives_first = true 31 | # Avoid "this." and "Me." if not necessary 32 | dotnet_style_qualification_for_field = false:suggestion 33 | dotnet_style_qualification_for_property = false:suggestion 34 | dotnet_style_qualification_for_method = false:suggestion 35 | dotnet_style_qualification_for_event = false:suggestion 36 | 37 | # Use language keywords instead of framework type names for type references 38 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion 39 | dotnet_style_predefined_type_for_member_access = true:suggestion 40 | 41 | # Suggest more modern language features when available 42 | dotnet_style_object_initializer = true:suggestion 43 | dotnet_style_collection_initializer = true:suggestion 44 | dotnet_style_coalesce_expression = true:suggestion 45 | dotnet_style_null_propagation = true:suggestion 46 | dotnet_style_explicit_tuple_names = true:suggestion 47 | 48 | # CSharp code style settings: 49 | [*.cs] 50 | csharp_style_var_for_built_in_types = false:suggestion 51 | csharp_style_var_when_type_is_apparent = false:suggestion 52 | csharp_style_var_elsewhere = false:suggestion 53 | 54 | # Prefer method-like constructs to have a block body 55 | csharp_style_expression_bodied_methods = false:none 56 | csharp_style_expression_bodied_constructors = false:none 57 | csharp_style_expression_bodied_operators = false:none 58 | 59 | # Prefer property-like constructs to have an expression-body 60 | csharp_style_expression_bodied_properties = true:none 61 | csharp_style_expression_bodied_indexers = true:none 62 | csharp_style_expression_bodied_accessors = true:none 63 | 64 | # Suggest more modern language features when available 65 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion 66 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion 67 | csharp_style_inlined_variable_declaration = true:suggestion 68 | csharp_style_throw_expression = true:suggestion 69 | csharp_style_conditional_delegate_call = true:suggestion 70 | 71 | # Newline settings 72 | csharp_new_line_before_open_brace = all 73 | csharp_new_line_before_else = true 74 | csharp_new_line_before_catch = true 75 | csharp_new_line_before_finally = true 76 | csharp_new_line_before_members_in_object_initializers = true 77 | csharp_new_line_before_members_in_anonymous_types = true 78 | 79 | # Known validation methods, see https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1062?view=vs-2019#null-check-validation-methods 80 | dotnet_code_quality.CA1062.null_check_validation_methods = ThrowIfNull|ThrowIfNullOrEmpty|ThrowIfNullOrWhiteSpace 81 | 82 | # These rules represent Dave Glick's preferences and enforce consistent code quality guidelines. 83 | [*.{cs,vb}] 84 | dotnet_diagnostic.CA1020.severity = warning 85 | dotnet_diagnostic.CA1021.severity = warning 86 | dotnet_diagnostic.CA1040.severity = warning 87 | dotnet_diagnostic.CA1045.severity = warning 88 | dotnet_diagnostic.CA1062.severity = warning 89 | dotnet_diagnostic.CA1501.severity = warning 90 | dotnet_diagnostic.CA1504.severity = warning 91 | dotnet_diagnostic.CA1505.severity = warning 92 | dotnet_diagnostic.CA1506.severity = none 93 | dotnet_diagnostic.CA1700.severity = warning 94 | dotnet_diagnostic.CA1701.severity = warning 95 | dotnet_diagnostic.CA1702.severity = warning 96 | dotnet_diagnostic.CA1703.severity = warning 97 | dotnet_diagnostic.CA1704.severity = warning 98 | dotnet_diagnostic.CA1707.severity = warning 99 | dotnet_diagnostic.CA1709.severity = warning 100 | dotnet_diagnostic.CA1710.severity = warning 101 | dotnet_diagnostic.CA1711.severity = warning 102 | dotnet_diagnostic.CA1712.severity = warning 103 | dotnet_diagnostic.CA1713.severity = warning 104 | dotnet_diagnostic.CA1714.severity = warning 105 | dotnet_diagnostic.CA1715.severity = warning 106 | dotnet_diagnostic.CA1717.severity = warning 107 | dotnet_diagnostic.CA1719.severity = warning 108 | dotnet_diagnostic.CA1720.severity = warning 109 | dotnet_diagnostic.CA1721.severity = warning 110 | dotnet_diagnostic.CA1722.severity = warning 111 | dotnet_diagnostic.CA1724.severity = none 112 | dotnet_diagnostic.CA1725.severity = warning 113 | dotnet_diagnostic.CA1726.severity = warning 114 | dotnet_diagnostic.CA2204.severity = warning 115 | dotnet_diagnostic.CS1591.severity = none 116 | dotnet_diagnostic.IDE0007.severity = none 117 | dotnet_diagnostic.IDE0007WithoutSuggestion.severity = none 118 | dotnet_diagnostic.IDE0008.severity = warning 119 | dotnet_diagnostic.RCS1001.severity = suggestion 120 | dotnet_diagnostic.RCS1002.severity = none 121 | dotnet_diagnostic.RCS1003.severity = suggestion 122 | dotnet_diagnostic.RCS1004.severity = none 123 | dotnet_diagnostic.RCS1005.severity = silent 124 | dotnet_diagnostic.RCS1006.severity = silent 125 | dotnet_diagnostic.RCS1007.severity = none 126 | dotnet_diagnostic.RCS1008.severity = warning 127 | dotnet_diagnostic.RCS1009.severity = warning 128 | dotnet_diagnostic.RCS1010.severity = none 129 | dotnet_diagnostic.RCS1012.severity = warning 130 | dotnet_diagnostic.RCS1013.severity = none 131 | dotnet_diagnostic.RCS1014.severity = none 132 | dotnet_diagnostic.RCS1015.severity = suggestion 133 | dotnet_diagnostic.RCS1016.severity = none 134 | dotnet_diagnostic.RCS1017.severity = none 135 | dotnet_diagnostic.RCS1018.severity = suggestion 136 | dotnet_diagnostic.RCS1019.severity = none 137 | dotnet_diagnostic.RCS1020.severity = suggestion 138 | dotnet_diagnostic.RCS1021.severity = suggestion 139 | dotnet_diagnostic.RCS1022.severity = none 140 | dotnet_diagnostic.RCS1023.severity = none 141 | dotnet_diagnostic.RCS1024.severity = none 142 | dotnet_diagnostic.RCS1025.severity = none 143 | dotnet_diagnostic.RCS1026.severity = none 144 | dotnet_diagnostic.RCS1027.severity = none 145 | dotnet_diagnostic.RCS1028.severity = none 146 | dotnet_diagnostic.RCS1029.severity = suggestion 147 | dotnet_diagnostic.RCS1030.severity = none 148 | dotnet_diagnostic.RCS1031.severity = suggestion 149 | dotnet_diagnostic.RCS1032.severity = suggestion 150 | dotnet_diagnostic.RCS1033.severity = suggestion 151 | dotnet_diagnostic.RCS1034.severity = silent 152 | dotnet_diagnostic.RCS1035.severity = none 153 | dotnet_diagnostic.RCS1036.severity = suggestion 154 | dotnet_diagnostic.RCS1037.severity = suggestion 155 | dotnet_diagnostic.RCS1038.severity = suggestion 156 | dotnet_diagnostic.RCS1039.severity = silent 157 | dotnet_diagnostic.RCS1040.severity = silent 158 | dotnet_diagnostic.RCS1041.severity = suggestion 159 | dotnet_diagnostic.RCS1042.severity = silent 160 | dotnet_diagnostic.RCS1043.severity = silent 161 | dotnet_diagnostic.RCS1044.severity = warning 162 | dotnet_diagnostic.RCS1045.severity = none 163 | dotnet_diagnostic.RCS1046.severity = none 164 | dotnet_diagnostic.RCS1047.severity = suggestion 165 | dotnet_diagnostic.RCS1048.severity = suggestion 166 | dotnet_diagnostic.RCS1049.severity = suggestion 167 | dotnet_diagnostic.RCS1050.severity = none 168 | dotnet_diagnostic.RCS1051.severity = none 169 | dotnet_diagnostic.RCS1052.severity = none 170 | dotnet_diagnostic.RCS1053.severity = none 171 | dotnet_diagnostic.RCS1054.severity = silent 172 | dotnet_diagnostic.RCS1055.severity = silent 173 | dotnet_diagnostic.RCS1056.severity = none 174 | dotnet_diagnostic.RCS1057.severity = suggestion 175 | dotnet_diagnostic.RCS1058.severity = suggestion 176 | dotnet_diagnostic.RCS1059.severity = warning 177 | dotnet_diagnostic.RCS1060.severity = none 178 | dotnet_diagnostic.RCS1061.severity = silent 179 | dotnet_diagnostic.RCS1062.severity = silent 180 | dotnet_diagnostic.RCS1063.severity = suggestion 181 | dotnet_diagnostic.RCS1064.severity = none 182 | dotnet_diagnostic.RCS1065.severity = none 183 | dotnet_diagnostic.RCS1066.severity = silent 184 | dotnet_diagnostic.RCS1067.severity = none 185 | dotnet_diagnostic.RCS1068.severity = suggestion 186 | dotnet_diagnostic.RCS1069.severity = silent 187 | dotnet_diagnostic.RCS1070.severity = silent 188 | dotnet_diagnostic.RCS1071.severity = silent 189 | dotnet_diagnostic.RCS1072.severity = suggestion 190 | dotnet_diagnostic.RCS1073.severity = suggestion 191 | dotnet_diagnostic.RCS1074.severity = silent 192 | dotnet_diagnostic.RCS1075.severity = none 193 | dotnet_diagnostic.RCS1076.severity = silent 194 | dotnet_diagnostic.RCS1077.severity = suggestion 195 | dotnet_diagnostic.RCS1078.severity = none 196 | dotnet_diagnostic.RCS1079.severity = none 197 | dotnet_diagnostic.RCS1080.severity = suggestion 198 | dotnet_diagnostic.RCS1081.severity = none 199 | dotnet_diagnostic.RCS1082.severity = warning 200 | dotnet_diagnostic.RCS1083.severity = warning 201 | dotnet_diagnostic.RCS1084.severity = suggestion 202 | dotnet_diagnostic.RCS1085.severity = suggestion 203 | dotnet_diagnostic.RCS1086.severity = none 204 | dotnet_diagnostic.RCS1087.severity = none 205 | dotnet_diagnostic.RCS1088.severity = none 206 | dotnet_diagnostic.RCS1089.severity = suggestion 207 | dotnet_diagnostic.RCS1090.severity = suggestion 208 | dotnet_diagnostic.RCS1091.severity = silent 209 | dotnet_diagnostic.RCS1092.severity = none 210 | dotnet_diagnostic.RCS1093.severity = suggestion 211 | dotnet_diagnostic.RCS1094.severity = none 212 | dotnet_diagnostic.RCS1095.severity = suggestion 213 | dotnet_diagnostic.RCS1096.severity = suggestion 214 | dotnet_diagnostic.RCS1097.severity = suggestion 215 | dotnet_diagnostic.RCS1098.severity = suggestion 216 | dotnet_diagnostic.RCS1099.severity = suggestion 217 | dotnet_diagnostic.RCS1100.severity = none 218 | dotnet_diagnostic.RCS1101.severity = none 219 | dotnet_diagnostic.RCS1102.severity = none 220 | dotnet_diagnostic.RCS1103.severity = suggestion 221 | dotnet_diagnostic.RCS1104.severity = suggestion 222 | dotnet_diagnostic.RCS1105.severity = suggestion 223 | dotnet_diagnostic.RCS1106.severity = suggestion 224 | dotnet_diagnostic.RCS1107.severity = suggestion 225 | dotnet_diagnostic.RCS1108.severity = suggestion 226 | dotnet_diagnostic.RCS1109.severity = suggestion 227 | dotnet_diagnostic.RCS1110.severity = suggestion 228 | dotnet_diagnostic.RCS1111.severity = none 229 | dotnet_diagnostic.RCS1112.severity = suggestion 230 | dotnet_diagnostic.RCS1113.severity = suggestion 231 | dotnet_diagnostic.RCS1114.severity = suggestion 232 | dotnet_diagnostic.RCS1115.severity = silent 233 | dotnet_diagnostic.RCS1116.severity = silent 234 | dotnet_diagnostic.RCS1117.severity = silent 235 | dotnet_diagnostic.RCS1118.severity = suggestion 236 | dotnet_diagnostic.RCS1119.severity = suggestion 237 | dotnet_diagnostic.RCS1120.severity = suggestion 238 | dotnet_diagnostic.RCS1121.severity = suggestion 239 | dotnet_diagnostic.RCS1122.severity = none 240 | dotnet_diagnostic.RCS1123.severity = suggestion 241 | dotnet_diagnostic.RCS1124.severity = silent 242 | dotnet_diagnostic.RCS1125.severity = silent 243 | dotnet_diagnostic.RCS1126.severity = none 244 | dotnet_diagnostic.RCS1127.severity = suggestion 245 | dotnet_diagnostic.RCS1128.severity = suggestion 246 | dotnet_diagnostic.RCS1129.severity = silent 247 | dotnet_diagnostic.RCS1130.severity = suggestion 248 | dotnet_diagnostic.RCS1131.severity = silent 249 | dotnet_diagnostic.RCS1132.severity = suggestion 250 | dotnet_diagnostic.RCS1133.severity = silent 251 | dotnet_diagnostic.RCS1134.severity = silent 252 | dotnet_diagnostic.RCS1135.severity = suggestion 253 | dotnet_diagnostic.RCS1136.severity = silent 254 | dotnet_diagnostic.RCS1137.severity = silent 255 | dotnet_diagnostic.RCS1138.severity = warning 256 | dotnet_diagnostic.RCS1139.severity = none 257 | dotnet_diagnostic.RCS1140.severity = silent 258 | dotnet_diagnostic.RCS1141.severity = silent 259 | dotnet_diagnostic.RCS1142.severity = silent 260 | dotnet_diagnostic.RCS1143.severity = silent 261 | dotnet_diagnostic.RCS1144.severity = silent 262 | dotnet_diagnostic.RCS1145.severity = silent 263 | dotnet_diagnostic.RCS1146.severity = suggestion 264 | dotnet_diagnostic.RCS1147.severity = silent 265 | dotnet_diagnostic.RCS1148.severity = silent 266 | dotnet_diagnostic.RCS1149.severity = silent 267 | dotnet_diagnostic.RCS1150.severity = suggestion 268 | dotnet_diagnostic.RCS1151.severity = silent 269 | dotnet_diagnostic.RCS1152.severity = silent 270 | dotnet_diagnostic.RCS1153.severity = none 271 | dotnet_diagnostic.RCS1154.severity = suggestion 272 | dotnet_diagnostic.RCS1155.severity = warning 273 | dotnet_diagnostic.RCS1156.severity = suggestion 274 | dotnet_diagnostic.RCS1157.severity = suggestion 275 | dotnet_diagnostic.RCS1158.severity = suggestion 276 | dotnet_diagnostic.RCS1159.severity = suggestion 277 | dotnet_diagnostic.RCS1160.severity = suggestion 278 | dotnet_diagnostic.RCS1161.severity = silent 279 | dotnet_diagnostic.RCS1162.severity = none 280 | dotnet_diagnostic.RCS1163.severity = suggestion 281 | dotnet_diagnostic.RCS1164.severity = suggestion 282 | dotnet_diagnostic.RCS1165.severity = silent 283 | dotnet_diagnostic.RCS1166.severity = suggestion 284 | dotnet_diagnostic.RCS1167.severity = silent 285 | dotnet_diagnostic.RCS1168.severity = none 286 | dotnet_diagnostic.RCS1169.severity = suggestion 287 | dotnet_diagnostic.RCS1170.severity = suggestion 288 | dotnet_diagnostic.RCS1171.severity = suggestion 289 | dotnet_diagnostic.RCS1172.severity = warning 290 | dotnet_diagnostic.RCS1173.severity = suggestion 291 | dotnet_diagnostic.RCS1174.severity = none 292 | dotnet_diagnostic.RCS1175.severity = suggestion 293 | dotnet_diagnostic.RCS1176.severity = none 294 | dotnet_diagnostic.RCS1177.severity = none 295 | dotnet_diagnostic.RCS1178.severity = suggestion 296 | dotnet_diagnostic.RCS1179.severity = suggestion 297 | dotnet_diagnostic.RCS1180.severity = suggestion 298 | dotnet_diagnostic.RCS1181.severity = silent 299 | dotnet_diagnostic.RCS1182.severity = silent 300 | dotnet_diagnostic.RCS1183.severity = silent 301 | dotnet_diagnostic.RCS1184.severity = none 302 | dotnet_diagnostic.RCS1185.severity = none 303 | dotnet_diagnostic.RCS1186.severity = silent 304 | dotnet_diagnostic.RCS1187.severity = suggestion 305 | dotnet_diagnostic.RCS1188.severity = silent 306 | dotnet_diagnostic.RCS1189.severity = silent 307 | dotnet_diagnostic.RCS1190.severity = suggestion 308 | dotnet_diagnostic.RCS1191.severity = suggestion 309 | dotnet_diagnostic.RCS1192.severity = suggestion 310 | dotnet_diagnostic.RCS1193.severity = warning 311 | dotnet_diagnostic.RCS1194.severity = none 312 | dotnet_diagnostic.RCS1195.severity = suggestion 313 | dotnet_diagnostic.RCS1196.severity = suggestion 314 | dotnet_diagnostic.RCS1197.severity = suggestion 315 | dotnet_diagnostic.RCS1198.severity = none 316 | dotnet_diagnostic.RCS1199.severity = suggestion 317 | dotnet_diagnostic.RCS1200.severity = suggestion 318 | dotnet_diagnostic.RCS1201.severity = silent 319 | dotnet_diagnostic.RCS1202.severity = suggestion 320 | dotnet_diagnostic.RCS1203.severity = warning 321 | dotnet_diagnostic.RCS1204.severity = suggestion 322 | dotnet_diagnostic.RCS1205.severity = suggestion 323 | dotnet_diagnostic.RCS1206.severity = suggestion 324 | dotnet_diagnostic.RCS1207.severity = silent 325 | dotnet_diagnostic.RCS1208.severity = none 326 | dotnet_diagnostic.RCS1209.severity = suggestion 327 | dotnet_diagnostic.RCS1210.severity = warning 328 | dotnet_diagnostic.RCS1211.severity = silent 329 | dotnet_diagnostic.RCS1212.severity = suggestion 330 | dotnet_diagnostic.RCS1213.severity = suggestion 331 | dotnet_diagnostic.RCS1214.severity = suggestion 332 | dotnet_diagnostic.RCS1215.severity = warning 333 | dotnet_diagnostic.RCS1216.severity = suggestion 334 | dotnet_diagnostic.RCS1217.severity = silent 335 | dotnet_diagnostic.RCS1218.severity = suggestion 336 | dotnet_diagnostic.RCS1219.severity = none 337 | dotnet_diagnostic.RCS1220.severity = suggestion 338 | dotnet_diagnostic.RCS1221.severity = suggestion 339 | dotnet_diagnostic.RCS1222.severity = suggestion 340 | dotnet_diagnostic.RCS1223.severity = none 341 | dotnet_diagnostic.RCS1224.severity = suggestion 342 | dotnet_diagnostic.RCS1225.severity = suggestion 343 | dotnet_diagnostic.RCS1226.severity = suggestion 344 | dotnet_diagnostic.RCS1227.severity = suggestion 345 | dotnet_diagnostic.RCS1228.severity = silent 346 | dotnet_diagnostic.RCS1229.severity = suggestion 347 | dotnet_diagnostic.RCS1230.severity = suggestion 348 | dotnet_diagnostic.RCS1231.severity = suggestion 349 | dotnet_diagnostic.SA1101.severity = none 350 | dotnet_diagnostic.SA1118.severity = none 351 | dotnet_diagnostic.SA1200.severity = none 352 | dotnet_diagnostic.SA1201.severity = none 353 | dotnet_diagnostic.SA1202.severity = none 354 | dotnet_diagnostic.SA1204.severity = none 355 | dotnet_diagnostic.SA1210.severity = none 356 | dotnet_diagnostic.SA1309.severity = none 357 | dotnet_diagnostic.SA1413.severity = none 358 | dotnet_diagnostic.SA1512.severity = none 359 | dotnet_diagnostic.SA1513.severity = none 360 | dotnet_diagnostic.SA1516.severity = none 361 | dotnet_diagnostic.SA1600.severity = none 362 | dotnet_diagnostic.SA1601.severity = none 363 | dotnet_diagnostic.SA1602.severity = none 364 | dotnet_diagnostic.SA1604.severity = none 365 | dotnet_diagnostic.SA1605.severity = none 366 | dotnet_diagnostic.SA1606.severity = none 367 | dotnet_diagnostic.SA1607.severity = none 368 | dotnet_diagnostic.SA1608.severity = none 369 | dotnet_diagnostic.SA1611.severity = none 370 | dotnet_diagnostic.SA1615.severity = none 371 | dotnet_diagnostic.SA1618.severity = none 372 | dotnet_diagnostic.SA1623.severity = none 373 | dotnet_diagnostic.SA1633.severity = none 374 | dotnet_diagnostic.SA1642.severity = none 375 | dotnet_diagnostic.SA1648.severity = none 376 | dotnet_diagnostic.SX1309.severity = warning -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: daveaglick 2 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | pull_request: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | jobs: 9 | build: 10 | name: Build 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | os: [windows-latest, ubuntu-latest, macos-latest] 16 | env: 17 | # https://github.com/NuGet/Home/issues/11548 18 | # https://twitter.com/xoofx/status/1488617114940452872?s=20&t=BKSN4j9rP6fOyg8l7aW0eg 19 | NUGET_CERT_REVOCATION_MODE: offline 20 | steps: 21 | - name: Get Source 22 | uses: actions/checkout@v2 23 | with: 24 | submodules: recursive 25 | - name: Install .NET Core SDK 26 | uses: actions/setup-dotnet@v1 27 | with: 28 | dotnet-version: | 29 | 3.1.x 30 | 6.0.x 31 | - name: Build and Test 32 | run: dotnet test --logger "trx;LogFileName=test-results.trx" 33 | - name: Upload Test Results 34 | uses: actions/upload-artifact@v2 35 | if: success() || failure() 36 | with: 37 | name: test-results-${{ matrix.os }} 38 | path: '**/test-results.trx' -------------------------------------------------------------------------------- /.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 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | [Oo]utput/ 27 | [Tt]est[Rr]esults/ 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 | .idea 206 | .vscode 207 | 208 | # Since there are multiple workflows, uncomment next line to ignore bower_components 209 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 210 | #bower_components/ 211 | 212 | # RIA/Silverlight projects 213 | Generated_Code/ 214 | 215 | # Backup & report files from converting an old project file 216 | # to a newer Visual Studio version. Backup files are not needed, 217 | # because we have git ;-) 218 | _UpgradeReport_Files/ 219 | Backup*/ 220 | UpgradeLog*.XML 221 | UpgradeLog*.htm 222 | 223 | # SQL Server files 224 | *.mdf 225 | *.ldf 226 | *.ndf 227 | 228 | # Business Intelligence projects 229 | *.rdl.data 230 | *.bim.layout 231 | *.bim_*.settings 232 | 233 | # Microsoft Fakes 234 | FakesAssemblies/ 235 | 236 | # GhostDoc plugin setting file 237 | *.GhostDoc.xml 238 | 239 | # Node.js Tools for Visual Studio 240 | .ntvs_analysis.dat 241 | node_modules/ 242 | 243 | # Typescript v1 declaration files 244 | typings/ 245 | 246 | # Visual Studio 6 build log 247 | *.plg 248 | 249 | # Visual Studio 6 workspace options file 250 | *.opt 251 | 252 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 253 | *.vbw 254 | 255 | # Visual Studio LightSwitch build output 256 | **/*.HTMLClient/GeneratedArtifacts 257 | **/*.DesktopClient/GeneratedArtifacts 258 | **/*.DesktopClient/ModelManifest.xml 259 | **/*.Server/GeneratedArtifacts 260 | **/*.Server/ModelManifest.xml 261 | _Pvt_Extensions 262 | 263 | # Paket dependency manager 264 | .paket/paket.exe 265 | paket-files/ 266 | 267 | # FAKE - F# Make 268 | .fake/ 269 | 270 | # JetBrains Rider 271 | .idea/ 272 | *.sln.iml 273 | 274 | # CodeRush 275 | .cr/ 276 | 277 | # Python Tools for Visual Studio (PTVS) 278 | __pycache__/ 279 | *.pyc 280 | 281 | # Docs 282 | docs/output/ 283 | docs/config.wyam.packages.xml 284 | docs/config.wyam.hash 285 | docs/config.wyam.dll 286 | 287 | # Telerik's JustMock configuration file 288 | *.jmconfig 289 | 290 | # BizTalk build output 291 | *.btp.cs 292 | *.btm.cs 293 | *.odx.cs 294 | *.xsd.cs 295 | 296 | *.ncrunchsolution 297 | 298 | *.ncrunchproject 299 | 300 | cache/ 301 | marvin/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "marvin"] 2 | path = marvin 3 | url = https://github.com/daveaglick/Marvin.git 4 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1.0.0 4 | $(NetlifySharpVersion) 5 | $(Version.Split('-')[0]) 6 | $(Version.Split('-')[0]) 7 | Dave Glick and contributors 8 | Dave Glick and contributors 9 | A .NET API Client for Netlify. 10 | icon.png 11 | README.md 12 | https://netlifysharp.netlify.com/ 13 | https://github.com/daveaglick/NetlifySharp.git 14 | git 15 | MIT 16 | false 17 | true 18 | true 19 | snupkg 20 | true 21 | true 22 | true 23 | true 24 | true 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Dave Glick 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /NetlifySharp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29409.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1D456B5E-2874-446C-8CFD-5134FC11ACAF}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetlifySharp", "src\NetlifySharp\NetlifySharp.csproj", "{41AF07B8-6EE0-4D1A-9E23-F42689059B9C}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{112DF2B8-84D8-46DA-995B-53D4DC30FBC7}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetlifySharp.Generator", "tools\NetlifySharp.Generator\NetlifySharp.Generator.csproj", "{7A593078-C658-4F01-B5F3-98C6AE646F0B}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {41AF07B8-6EE0-4D1A-9E23-F42689059B9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {41AF07B8-6EE0-4D1A-9E23-F42689059B9C}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {41AF07B8-6EE0-4D1A-9E23-F42689059B9C}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {41AF07B8-6EE0-4D1A-9E23-F42689059B9C}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {7A593078-C658-4F01-B5F3-98C6AE646F0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {7A593078-C658-4F01-B5F3-98C6AE646F0B}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {7A593078-C658-4F01-B5F3-98C6AE646F0B}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {7A593078-C658-4F01-B5F3-98C6AE646F0B}.Release|Any CPU.Build.0 = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | GlobalSection(NestedProjects) = preSolution 33 | {41AF07B8-6EE0-4D1A-9E23-F42689059B9C} = {1D456B5E-2874-446C-8CFD-5134FC11ACAF} 34 | {7A593078-C658-4F01-B5F3-98C6AE646F0B} = {112DF2B8-84D8-46DA-995B-53D4DC30FBC7} 35 | EndGlobalSection 36 | GlobalSection(ExtensibilityGlobals) = postSolution 37 | SolutionGuid = {17A4CA1C-8EEE-4D62-A5F2-06B88FEF22CB} 38 | EndGlobalSection 39 | EndGlobal 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NetlifySharp 2 | 3 | A .NET API Client for Netlify 4 | 5 | **NuGet** 6 | * [NetlifySharp](https://www.nuget.org/packages/NetlifySharp/) 7 | 8 | **GitHub** 9 | * [NetlifySharp](https://github.com/daveaglick/NetlifySharp) 10 | 11 | **Donations** 12 | 13 | If you found this library useful, consider [sponsoring more of it on GitHub](https://github.com/sponsors/daveaglick). I promise to use it on something totally frivolous and unrelated. 14 | 15 | [![Sponsor](https://img.shields.io/github/sponsors/daveaglick?style=social&logo=github-sponsors)](https://github.com/sponsors/daveaglick) 16 | 17 | View the docs at [http://netlifysharp.netlify.com/](http://netlifysharp.netlify.com/) for more information. -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # 1.1.1 2 | 3 | - Added a fallback `HttpClient` when `null` is passed to the constructor that accepts one (#4, thanks @MikDal002). 4 | 5 | # 1.1.0 6 | 7 | - Added a `NetlifyClient` constructor that does not require an `HttpClient`. 8 | - Added client methods to all model types as appropriate. 9 | 10 | # 1.0.0 11 | 12 | - Complete rewrite using NSwag to generate entire Open API specification. 13 | 14 | # 0.1.0 15 | 16 | - Initial release. -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd "build\NetlifySharp.Build" 3 | dotnet run -- %* 4 | set exitcode=%errorlevel% 5 | cd %~dp0 6 | exit /b %exitcode% -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daveaglick/NetlifySharp/d3bebf8ab754b6cb86aedf02fba474be0bfa538e/icon.png -------------------------------------------------------------------------------- /marvin.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd "marvin" 3 | dotnet run -- %* 4 | set exitcode=%errorlevel% 5 | cd %~dp0 6 | exit /b %exitcode% -------------------------------------------------------------------------------- /marvin.yml: -------------------------------------------------------------------------------- 1 | ProjectSets: 2 | - Name: NetlifySharp 3 | SourceProjects: "src/*/*.csproj" 4 | TestProjects: "tests/*/*.csproj" 5 | GitHubOwner: "daveaglick" 6 | GitHubName: "NetlifySharp" 7 | GitHubToken: => GetString("GITHUB_TOKEN") 8 | NuGetApiKey: => GetString("DAVEAGLICK_NUGET_API_KEY") -------------------------------------------------------------------------------- /src/NetlifySharp/ClientModelCreationConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.IO.Compression; 5 | using System.Linq; 6 | using System.Net.Http; 7 | using System.Reflection; 8 | using System.Runtime.CompilerServices; 9 | using System.Threading.Tasks; 10 | using Newtonsoft.Json; 11 | using Newtonsoft.Json.Converters; 12 | 13 | namespace NetlifySharp 14 | { 15 | internal class ClientModelCreationConverter : CustomCreationConverter 16 | { 17 | private readonly NetlifyClient _client; 18 | 19 | public ClientModelCreationConverter(NetlifyClient client) 20 | { 21 | _client = client; 22 | } 23 | 24 | public override bool CanConvert(Type objectType) 25 | { 26 | TypeInfo typeInfo = objectType.GetTypeInfo(); 27 | return typeof(IClientModel).GetTypeInfo().IsAssignableFrom(typeInfo) 28 | && typeInfo.DeclaredConstructors.Any(x => 29 | { 30 | ParameterInfo[] parameters = x.GetParameters(); 31 | return x.IsPublic && parameters.Length == 1 && parameters[0].ParameterType == typeof(NetlifyClient); 32 | }); 33 | } 34 | 35 | public override object Create(Type objectType) => Activator.CreateInstance(objectType, _client); 36 | } 37 | } -------------------------------------------------------------------------------- /src/NetlifySharp/HttpClientWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.IO.Compression; 5 | using System.Linq; 6 | using System.Net.Http; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | using Newtonsoft.Json.Converters; 10 | 11 | namespace NetlifySharp 12 | { 13 | // A HttpClient wrapper that doesn't dispose the underlying HttpClient 14 | internal class HttpClientWrapper : HttpClient 15 | { 16 | private readonly HttpClient _httpClient; 17 | 18 | public HttpClientWrapper(HttpClient httpClient) 19 | { 20 | _httpClient = httpClient; 21 | } 22 | 23 | public override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => 24 | _httpClient.SendAsync(request, cancellationToken); 25 | } 26 | } -------------------------------------------------------------------------------- /src/NetlifySharp/IClientModel.cs: -------------------------------------------------------------------------------- 1 | namespace NetlifySharp 2 | { 3 | public interface IClientModel 4 | { 5 | NetlifyClient Client { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/NetlifySharp/NetlifyClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.IO.Compression; 5 | using System.Linq; 6 | using System.Net.Http; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | using Newtonsoft.Json.Converters; 10 | 11 | namespace NetlifySharp 12 | { 13 | public partial class NetlifyClient 14 | { 15 | private readonly string _accessToken; 16 | private readonly HttpClient _httpClient; // The HttpClient if provided 17 | 18 | public NetlifyClient(string accessToken) 19 | : this(accessToken, null) 20 | { 21 | } 22 | 23 | public NetlifyClient(string accessToken, HttpClient httpClient) 24 | : this() 25 | { 26 | _accessToken = accessToken ?? throw new ArgumentNullException(nameof(accessToken)); 27 | if (accessToken.Any(x => char.IsWhiteSpace(x) || char.IsControl(x))) 28 | { 29 | throw new ArgumentException("Invalid access token", nameof(accessToken)); 30 | } 31 | _httpClient = httpClient ?? CreateHttpClient(); 32 | } 33 | 34 | private Task CreateHttpClientAsync(CancellationToken cancellationToken) => 35 | Task.FromResult(CreateHttpClient()); 36 | 37 | private HttpClient CreateHttpClient() 38 | => _httpClient == null ? new HttpClient() : new HttpClientWrapper(_httpClient); 39 | 40 | partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings) 41 | { 42 | settings.Converters.Add(new ClientModelCreationConverter(this)); 43 | } 44 | 45 | partial void PrepareRequest(HttpClient client, HttpRequestMessage request, string url) 46 | { 47 | request.Headers.Add("User-Agent", nameof(NetlifySharp)); 48 | request.Headers.Add("Authorization", "Bearer " + _accessToken); 49 | } 50 | 51 | public Task UpdateSiteAsync(Stream zipStream, string siteId) => 52 | UpdateSiteAsync(zipStream, siteId, System.Threading.CancellationToken.None); 53 | 54 | public async Task UpdateSiteAsync(Stream zipStream, string siteId, System.Threading.CancellationToken cancellationToken) 55 | { 56 | _ = siteId ?? throw new ArgumentNullException(nameof(siteId)); 57 | 58 | System.Text.StringBuilder urlBuilder_ = new System.Text.StringBuilder(); 59 | urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : string.Empty).Append("/sites/{site_id}"); 60 | urlBuilder_.Replace("{site_id}", Uri.EscapeDataString(ConvertToString(siteId, System.Globalization.CultureInfo.InvariantCulture))); 61 | 62 | HttpClient client_ = _httpClient; 63 | try 64 | { 65 | using (HttpRequestMessage request_ = new HttpRequestMessage()) 66 | { 67 | StreamContent content_ = new StreamContent(zipStream); 68 | content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/zip"); 69 | request_.Content = content_; 70 | request_.Method = new HttpMethod("PUT"); 71 | request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); 72 | 73 | PrepareRequest(client_, request_, urlBuilder_); 74 | string url_ = urlBuilder_.ToString(); 75 | request_.RequestUri = new Uri(url_, UriKind.RelativeOrAbsolute); 76 | PrepareRequest(client_, request_, url_); 77 | 78 | HttpResponseMessage response_ = await client_.SendAsync(request_, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); 79 | try 80 | { 81 | Dictionary> headers_ = Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); 82 | if (response_.Content != null && response_.Content.Headers != null) 83 | { 84 | foreach (KeyValuePair> item_ in response_.Content.Headers) 85 | { 86 | headers_[item_.Key] = item_.Value; 87 | } 88 | } 89 | 90 | ProcessResponse(client_, response_); 91 | 92 | string status_ = ((int)response_.StatusCode).ToString(); 93 | if (status_ == "200") 94 | { 95 | ObjectResponseResult objectResponse_ = await ReadObjectResponseAsync(response_, headers_).ConfigureAwait(false); 96 | return objectResponse_.Object; 97 | } 98 | else 99 | { 100 | ObjectResponseResult objectResponse_ = await ReadObjectResponseAsync(response_, headers_).ConfigureAwait(false); 101 | throw new NetlifyException("error", (int)response_.StatusCode, objectResponse_.Text, headers_, objectResponse_.Object, null); 102 | } 103 | } 104 | finally 105 | { 106 | if (response_ != null) 107 | { 108 | response_.Dispose(); 109 | } 110 | } 111 | } 112 | } 113 | finally 114 | { 115 | } 116 | } 117 | 118 | public Task UpdateSiteAsync(string directory, string siteId) => 119 | UpdateSiteAsync(directory, siteId, System.Threading.CancellationToken.None); 120 | 121 | public Task UpdateSiteAsync(string directory, string siteId, System.Threading.CancellationToken cancellationToken) 122 | { 123 | _ = directory ?? throw new ArgumentNullException(nameof(directory)); 124 | if (!Directory.Exists(directory)) 125 | { 126 | throw new ArgumentException("The directory must exist", nameof(directory)); 127 | } 128 | 129 | MemoryStream zipStream = new MemoryStream(); 130 | using (ZipArchive zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) 131 | { 132 | directory = Path.GetFullPath(directory); 133 | int startIndex = directory.Length + 1; 134 | foreach (string file in Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories)) 135 | { 136 | // We need to normalize the path separator so non-Windows Netlify systems can unzip it 137 | zipArchive.CreateEntryFromFile(file, Path.GetFullPath(file).Substring(startIndex).Replace('\\', '/')); 138 | } 139 | } 140 | zipStream.Position = 0; 141 | 142 | return UpdateSiteAsync(zipStream, siteId, cancellationToken); 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /src/NetlifySharp/NetlifyException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NetlifySharp 4 | { 5 | public partial class NetlifyException : Exception 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /src/NetlifySharp/NetlifySharp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard1.4 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/NetlifySharp/Site.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.IO.Compression; 5 | using System.Linq; 6 | using System.Net.Http; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | using Newtonsoft.Json.Converters; 10 | 11 | namespace NetlifySharp 12 | { 13 | public partial class Site 14 | { 15 | public Task UpdateSiteAsync(Stream zipStream) => Client.UpdateSiteAsync(zipStream, Id); 16 | public Task UpdateSiteAsync(Stream zipStream, CancellationToken cancellationToken) => Client.UpdateSiteAsync(zipStream, Id, cancellationToken); 17 | public Task UpdateSiteAsync(string directory) => Client.UpdateSiteAsync(directory, Id); 18 | public Task UpdateSiteAsync(string directory, CancellationToken cancellationToken) => Client.UpdateSiteAsync(directory, Id, cancellationToken); 19 | } 20 | } -------------------------------------------------------------------------------- /stylecop.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 3 | "settings": { 4 | "orderingRules": { 5 | "usingDirectivesPlacement": "outsideNamespace" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /tests.ruleset: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /tools/NetlifySharp.Generator/CamelCaseParameterNameGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using NJsonSchema; 7 | using NJsonSchema.CodeGeneration; 8 | using NJsonSchema.CodeGeneration.CSharp; 9 | using NSwag; 10 | using NSwag.CodeGeneration; 11 | using NSwag.CodeGeneration.CSharp; 12 | 13 | namespace NetlifySharp.Generator 14 | { 15 | public class CamelCaseParameterNameGenerator : IParameterNameGenerator 16 | { 17 | public string Generate(OpenApiParameter parameter, IEnumerable allParameters) => 18 | string.Concat( 19 | parameter.Name 20 | .Split(new char[] { '_', '-' }, StringSplitOptions.RemoveEmptyEntries) 21 | .Select((x, i) => i == 0 ? x : (x.Length > 1 ? char.ToUpperInvariant(x[0]) + x.Substring(1) : x.ToUpperInvariant()))); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tools/NetlifySharp.Generator/ClassBodyTemplate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | using NJsonSchema.CodeGeneration; 7 | using NJsonSchema.CodeGeneration.CSharp.Models; 8 | using NSwag.CodeGeneration.CSharp; 9 | using NSwag.CodeGeneration.CSharp.Models; 10 | 11 | namespace NetlifySharp.Generator 12 | { 13 | public class ClassBodyTemplate : ITemplate 14 | { 15 | private static readonly ClientCall[] ClientCalls = new ClientCall[] 16 | { 17 | new ClientCall("Site", "string", "siteId", "Id", "GetSite"), 18 | new ClientCall("AccountMembership", "string", "accountId", "Id", "GetAccount"), 19 | new ClientCall("Hook", "string", "hookId", "Id", "GetHook"), 20 | new ClientCall("Deploy", "string", "deployId", "Id", "GetDeploy", "GetSiteDeploy", "UpdateSiteDeploy", "RestoreSiteDeploy"), 21 | new ClientCall("Form", "string", "formId", "Id"), 22 | new ClientCall("Build", "string", "buildId", "Id", "GetSiteBuild") 23 | }; 24 | 25 | private readonly ClassTemplateModel _classTemplateModel; 26 | 27 | private readonly CSharpClientTemplateModel _clientTemplateModel; 28 | 29 | public ClassBodyTemplate(ClassTemplateModel classTemplateModel, CSharpClientTemplateModel clientTemplateModel) 30 | { 31 | _classTemplateModel = classTemplateModel ?? throw new ArgumentNullException(nameof(classTemplateModel)); 32 | _clientTemplateModel = clientTemplateModel ?? throw new ArgumentNullException(nameof(clientTemplateModel)); 33 | } 34 | 35 | public string Render() 36 | { 37 | StringBuilder builder = new StringBuilder(); 38 | builder.AppendLine("// Client methods"); 39 | foreach (ClientCall clientCall in ClientCalls.Where(x => x.ClassName == _classTemplateModel.ClassName)) 40 | { 41 | foreach (CSharpOperationModel operation in _clientTemplateModel.Operations 42 | .Where(x => x.Parameters.Any(p => p.Type == clientCall.ParameterType && p.VariableName == clientCall.VariableName) 43 | && !clientCall.ExcludedMethods.Contains(x.ActualOperationName))) 44 | { 45 | BuildMethod(builder, clientCall, operation, false); 46 | BuildMethod(builder, clientCall, operation, true); 47 | } 48 | } 49 | return builder.ToString(); 50 | } 51 | 52 | private static void BuildMethod(StringBuilder builder, ClientCall clientCall, CSharpOperationModel operation, bool cancellationToken) 53 | { 54 | builder.Append($"public {operation.ResultType} {operation.ActualOperationName}Async("); 55 | BuildParameters(builder, clientCall, operation, cancellationToken, false); 56 | builder.Append($") => Client.{operation.ActualOperationName}Async("); 57 | BuildParameters(builder, clientCall, operation, cancellationToken, true); 58 | builder.AppendLine(");"); 59 | } 60 | 61 | private static void BuildParameters(StringBuilder builder, ClientCall clientCall, CSharpOperationModel operation, bool cancellationToken, bool call) 62 | { 63 | bool comma = false; 64 | 65 | // Build the parameters 66 | foreach (CSharpParameterModel parameter in operation.Parameters) 67 | { 68 | if (parameter.VariableName != clientCall.VariableName) 69 | { 70 | if (comma) 71 | { 72 | builder.Append(", "); 73 | } 74 | if (!call) 75 | { 76 | builder.Append($"{parameter.Type} "); 77 | } 78 | builder.Append(parameter.VariableName); 79 | comma = true; 80 | } 81 | else if (call) 82 | { 83 | if (comma) 84 | { 85 | builder.Append(", "); 86 | } 87 | builder.Append(clientCall.ModelProperty); 88 | comma = true; 89 | } 90 | } 91 | 92 | // Add the cancellation token 93 | if (cancellationToken) 94 | { 95 | if (comma) 96 | { 97 | builder.Append(", "); 98 | } 99 | if (!call) 100 | { 101 | builder.Append("System.Threading.CancellationToken "); 102 | } 103 | builder.Append("cancellationToken"); 104 | } 105 | } 106 | 107 | public class ClientCall 108 | { 109 | public ClientCall(string className, string parameterType, string variableName, string modelProperty, params string[] excludedMethods) 110 | { 111 | ClassName = className; 112 | ParameterType = parameterType; 113 | VariableName = variableName; 114 | ModelProperty = modelProperty; 115 | ExcludedMethods = excludedMethods; 116 | } 117 | 118 | public string ClassName { get; } 119 | 120 | public string ParameterType { get; } 121 | 122 | public string VariableName { get; } 123 | 124 | public string ModelProperty { get; } 125 | 126 | public string[] ExcludedMethods { get; } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /tools/NetlifySharp.Generator/ClassConstructorTemplate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NJsonSchema.CodeGeneration; 3 | using NJsonSchema.CodeGeneration.CSharp.Models; 4 | using NSwag.CodeGeneration.CSharp; 5 | 6 | namespace NetlifySharp.Generator 7 | { 8 | public class ClassConstructorTemplate : ITemplate 9 | { 10 | private readonly ClassTemplateModel _classTemplateModel; 11 | private readonly CSharpClientGeneratorSettings _clientSettings; 12 | 13 | public ClassConstructorTemplate(ClassTemplateModel classTemplateModel, CSharpClientGeneratorSettings clientSettings) 14 | { 15 | _classTemplateModel = classTemplateModel ?? throw new ArgumentNullException(nameof(classTemplateModel)); 16 | _clientSettings = clientSettings ?? throw new ArgumentNullException(nameof(clientSettings)); 17 | } 18 | 19 | public string Render() 20 | { 21 | if (string.IsNullOrEmpty(_classTemplateModel.BaseClassName) 22 | || _classTemplateModel.BaseClassName.StartsWith("System.")) 23 | { 24 | // No base class 25 | return @$"public {_classTemplateModel.ClassName}({_clientSettings.ClassName} client) 26 | {{ 27 | Client = client ?? throw new System.ArgumentNullException(nameof(client)); 28 | }} 29 | 30 | [Newtonsoft.Json.JsonIgnore] 31 | public {_clientSettings.ClassName} Client {{ get; internal set; }} 32 | 33 | // Serializable properties"; 34 | } 35 | 36 | // Base class 37 | return @$"public {_classTemplateModel.ClassName}({_clientSettings.ClassName} client) : base(client) 38 | {{ 39 | }} 40 | 41 | // Serializable properties"; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tools/NetlifySharp.Generator/ClassInheritanceTemplate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NJsonSchema.CodeGeneration; 3 | using NSwag.CodeGeneration.CSharp; 4 | 5 | namespace NetlifySharp.Generator 6 | { 7 | public class ClassInheritanceTemplate : ITemplate 8 | { 9 | private readonly ITemplate _template; 10 | 11 | public ClassInheritanceTemplate(ITemplate template) 12 | { 13 | _template = template ?? throw new ArgumentNullException(nameof(template)); 14 | } 15 | 16 | public string Render() 17 | { 18 | string render = _template.Render(); 19 | render += string.IsNullOrEmpty(render) ? ": IClientModel" : ", IClientModel"; 20 | return render; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tools/NetlifySharp.Generator/CustomTemplateFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using NJsonSchema.CodeGeneration; 6 | using NJsonSchema.CodeGeneration.CSharp.Models; 7 | using NSwag.CodeGeneration.CSharp; 8 | using NSwag.CodeGeneration.CSharp.Models; 9 | 10 | namespace NetlifySharp.Generator 11 | { 12 | public class CustomTemplateFactory : ITemplateFactory 13 | { 14 | private static readonly PropertyInfo HashObjectProperty = typeof(ITemplateFactory) 15 | .Assembly 16 | .GetTypes() 17 | .First(x => x.Name == "LiquidProxyHash") 18 | .GetTypeInfo() 19 | .GetProperty("Object"); 20 | 21 | private readonly ITemplateFactory _defaultFactory; 22 | 23 | private readonly CSharpClientGeneratorSettings _clientSettings; 24 | 25 | private CSharpClientTemplateModel _clientTemplateModel = null; 26 | 27 | public CustomTemplateFactory(ITemplateFactory defaultFactory, CSharpClientGeneratorSettings clientSettings) 28 | { 29 | _defaultFactory = defaultFactory; 30 | _clientSettings = clientSettings; 31 | } 32 | 33 | public ITemplate CreateTemplate(string language, string templateName, object model) 34 | { 35 | ITemplate template = _defaultFactory.CreateTemplate(language, templateName, model); 36 | if (templateName.StartsWith("Client.Class.Body")) 37 | { 38 | // This gets called before the Class.Body template so use it to get the client template model 39 | _clientTemplateModel = (CSharpClientTemplateModel)HashObjectProperty.GetValue(model); 40 | } 41 | if (templateName.StartsWith("Class.Body")) 42 | { 43 | // Get all the operations so we can create proxies in the model objects 44 | ClassTemplateModel classTemplateModel = (ClassTemplateModel)HashObjectProperty.GetValue(model); 45 | return new ClassBodyTemplate(classTemplateModel, _clientTemplateModel); 46 | } 47 | if (templateName == "Class.Inheritance") 48 | { 49 | // Add IClientModel to the interface list 50 | return new ClassInheritanceTemplate(template); 51 | } 52 | if (templateName == "Class.Constructor") 53 | { 54 | // Changes the constructor to take a NetlifyClient 55 | ClassTemplateModel classTemplateModel = (ClassTemplateModel)HashObjectProperty.GetValue(model); 56 | return new ClassConstructorTemplate(classTemplateModel, _clientSettings); 57 | } 58 | return template; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /tools/NetlifySharp.Generator/NetlifySharp.Generator.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.0 6 | $(MSBuildProjectDirectory) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tools/NetlifySharp.Generator/PascalCasePropertyNameGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using NJsonSchema; 6 | using NJsonSchema.CodeGeneration; 7 | using NJsonSchema.CodeGeneration.CSharp; 8 | using NSwag; 9 | using NSwag.CodeGeneration.CSharp; 10 | 11 | namespace NetlifySharp.Generator 12 | { 13 | public class PascalCasePropertyNameGenerator : IPropertyNameGenerator 14 | { 15 | public string Generate(JsonSchemaProperty property) => 16 | string.Concat( 17 | property.Name 18 | .Split(new char[] { '_', '-' }, StringSplitOptions.RemoveEmptyEntries) 19 | .Select(x => x.Length > 1 ? char.ToUpperInvariant(x[0]) + x.Substring(1) : x.ToUpperInvariant())); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tools/NetlifySharp.Generator/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 NJsonSchema; 7 | using NJsonSchema.CodeGeneration; 8 | using NJsonSchema.CodeGeneration.CSharp; 9 | using NJsonSchema.CodeGeneration.CSharp.Models; 10 | using NSwag; 11 | using NSwag.CodeGeneration; 12 | using NSwag.CodeGeneration.CSharp; 13 | 14 | namespace NetlifySharp.Generator 15 | { 16 | public class Program 17 | { 18 | public static async Task Main(string[] args) 19 | { 20 | // Read the Open API YAML specification 21 | OpenApiDocument document = await OpenApiYamlDocument.FromUrlAsync("https://raw.githubusercontent.com/netlify/open-api/master/swagger.yml"); 22 | 23 | // Generate the code 24 | CSharpClientGeneratorSettings clientSettings = new CSharpClientGeneratorSettings 25 | { 26 | ClassName = nameof(NetlifyClient), 27 | CSharpGeneratorSettings = 28 | { 29 | Namespace = nameof(NetlifySharp), 30 | PropertyNameGenerator = new PascalCasePropertyNameGenerator() 31 | }, 32 | ParameterNameGenerator = new CamelCaseParameterNameGenerator(), 33 | ExceptionClass = nameof(NetlifyException), 34 | InjectHttpClient = false, 35 | UseHttpClientCreationMethod = true 36 | }; 37 | clientSettings.CSharpGeneratorSettings.TemplateFactory = new CustomTemplateFactory( 38 | clientSettings.CSharpGeneratorSettings.TemplateFactory, 39 | clientSettings); 40 | CSharpClientGenerator generator = new CSharpClientGenerator(document, clientSettings); 41 | string code = generator.GenerateFile(); 42 | 43 | // Make the constructor private so we can write our own 44 | code = code.Replace($"public {clientSettings.ClassName}(", $"private {clientSettings.ClassName}("); 45 | 46 | // Write to a file in the client project 47 | System.IO.File.WriteAllText($"../../src/NetlifySharp/{clientSettings.ClassName}.Generated.cs", code); 48 | } 49 | } 50 | } 51 | --------------------------------------------------------------------------------