Skip to content

Commit c7d6b45

Browse files
committed
Formatted Star Wars sample code
1 parent d0151c3 commit c7d6b45

File tree

6 files changed

+293
-236
lines changed

6 files changed

+293
-236
lines changed

samples/star-wars-api/MultipartRequest.fs

Lines changed: 87 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,16 @@ open FSharp.Data.GraphQL.Ast
1212

1313
[<Struct>]
1414
type GraphQLMultipartSection =
15-
| Form of Form: FormMultipartSection
16-
| File of File: FileMultipartSection
17-
static member FromSection(section : MultipartSection) =
15+
| Form of Form : FormMultipartSection
16+
| File of File : FileMultipartSection
17+
18+
static member FromSection (section : MultipartSection) =
1819
match section with
1920
| null -> ValueNone
2021
| _ ->
21-
match section.AsFormDataSection() with
22+
match section.AsFormDataSection () with
2223
| null ->
23-
match section.AsFileSection() with
24+
match section.AsFileSection () with
2425
| null -> ValueNone
2526
| x -> ValueSome (File x)
2627
| x -> ValueSome (Form x)
@@ -33,14 +34,21 @@ type GraphQLMultipartSection =
3334
/// <remarks> For more information, see https://github.com/jaydenseric/graphql-multipart-request-spec. </remarks>
3435
[<Struct>]
3536
type MultipartRequest =
36-
/// Contains the list of operations of this request.
37-
/// If the request is not batched, then the single operation will be inside this list as a singleton.
38-
{ Operations : GQLRequestContent list }
37+
/// Contains the list of operations of this request.
38+
/// If the request is not batched, then the single operation will be inside this list as a singleton.
39+
{
40+
Operations : GQLRequestContent list
41+
}
3942

4043
/// Contains tools for working with GraphQL multipart requests.
4144
module MultipartRequest =
4245

43-
let private parseOperations (jsonOptions: JsonSerializerOptions) (operations: GQLRequestContent list) (map : IDictionary<string, string>) (files : IDictionary<string, File>) =
46+
let private parseOperations
47+
(jsonOptions : JsonSerializerOptions)
48+
(operations : GQLRequestContent list)
49+
(map : IDictionary<string, string>)
50+
(files : IDictionary<string, File>)
51+
=
4452

4553
let mapOperation (operationIndex : int voption) (operation : GQLRequestContent) =
4654
let findFile (varName : string) (varValue : JsonElement) = seq {
@@ -50,8 +58,9 @@ module MultipartRequest =
5058
| (true, v) -> Some v
5159
| _ -> None)
5260
|> Seq.map (fun key ->
53-
key |> Option.map (fun key ->
54-
match files.TryGetValue(key) with
61+
key
62+
|> Option.map (fun key ->
63+
match files.TryGetValue (key) with
5564
| (true, v) -> Some v
5665
| _ -> None)
5766
|> Option.flatten)
@@ -66,40 +75,47 @@ module MultipartRequest =
6675
|> Seq.choose (fun kvp -> if kvp.Key = varName then Some files.[kvp.Value] else None)
6776
|> List.ofSeq
6877
match found with
69-
| [x] -> Some x
78+
| [ x ] -> Some x
7079
| _ -> None
7180
let pickSingleFileFromMap varName =
7281
map
7382
|> Seq.choose (fun kvp -> if kvp.Key = varName then Some files.[kvp.Value] else None)
7483
|> Seq.exactlyOne
75-
let pickFileRequestFromMap (request : UploadRequest) varName : UploadRequest =
76-
{ Single = pickSingleFileFromMap $"%s{varName}.single"
77-
Multiple = pickMultipleFilesFromMap request.Multiple.Length $"%s{varName}.multiple"
78-
NullableMultiple = request.NullableMultiple |> Option.map (fun x -> pickMultipleFilesFromMap x.Length $"%s{varName}.nullableMultiple")
79-
NullableMultipleNullable = request.NullableMultipleNullable |> Option.map (fun x -> tryPickMultipleFilesFromMap x.Length $"%s{varName}.nullableMultipleNullable") }
84+
let pickFileRequestFromMap (request : UploadRequest) varName : UploadRequest = {
85+
Single = pickSingleFileFromMap $"%s{varName}.single"
86+
Multiple = pickMultipleFilesFromMap request.Multiple.Length $"%s{varName}.multiple"
87+
NullableMultiple =
88+
request.NullableMultiple
89+
|> Option.map (fun x -> pickMultipleFilesFromMap x.Length $"%s{varName}.nullableMultiple")
90+
NullableMultipleNullable =
91+
request.NullableMultipleNullable
92+
|> Option.map (fun x -> tryPickMultipleFilesFromMap x.Length $"%s{varName}.nullableMultipleNullable")
93+
}
8094
let rec isUpload (t : InputType) =
8195
match t with
8296
| NamedType tname -> tname = "Upload" || tname = "UploadRequest"
83-
| ListType t | NonNullType t -> isUpload t
97+
| ListType t
98+
| NonNullType t -> isUpload t
8499
let ast = Parser.parse operation.Query
85100
let varDefs =
86101
ast.Definitions
87-
|> List.choose (function OperationDefinition def -> Some def.VariableDefinitions | _ -> None)
102+
|> List.choose (function
103+
| OperationDefinition def -> Some def.VariableDefinitions
104+
| _ -> None)
88105
|> List.collect id
89106
let varDef = varDefs |> List.find (fun x -> x.VariableName = varName)
90-
if isUpload varDef.Type
91-
then
107+
if isUpload varDef.Type then
92108
match varValue.ValueKind with
93109
| JsonValueKind.Object ->
94-
let request = varValue.Deserialize<UploadRequest>(jsonOptions)
110+
let request = varValue.Deserialize<UploadRequest> (jsonOptions)
95111
let varName =
96112
match operationIndex with
97113
| ValueSome operationIndex -> $"%i{operationIndex}.variables.%s{varName}"
98114
| ValueNone -> $"variables.%s{varName}"
99115
yield pickFileRequestFromMap request varName
100116
| JsonValueKind.Array ->
101117
let files =
102-
varValue.EnumerateArray()
118+
varValue.EnumerateArray ()
103119
|> Seq.mapi (fun valueIndex _ ->
104120
let varName =
105121
match operationIndex with
@@ -117,49 +133,58 @@ module MultipartRequest =
117133
| Some File -> yield file
118134
| None -> ()
119135
}
120-
{ operation with Variables = operation.Variables |> Skippable.map (Map.map (fun k v -> findFile k v)) }
136+
{
137+
operation with
138+
Variables =
139+
operation.Variables
140+
|> Skippable.map (Map.map (fun k v -> findFile k v))
141+
}
121142

122143
match operations with
123144
| [ operation ] -> [ mapOperation ValueNone operation ]
124-
| operations -> operations |> List.mapi (fun ix operation -> mapOperation (ValueSome ix) operation)
145+
| operations ->
146+
operations
147+
|> List.mapi (fun ix operation -> mapOperation (ValueSome ix) operation)
125148

126149
/// Reads a GraphQL multipart request from a MultipartReader.
127-
let read (jsonOptions: JsonSerializerOptions) cancellationToken (reader : MultipartReader) =
128-
task {
129-
let mutable section : GraphQLMultipartSection voption = ValueNone
130-
let readNextSection () =
131-
task {
132-
let! next = reader.ReadNextSectionAsync cancellationToken
133-
section <- GraphQLMultipartSection.FromSection(next)
150+
let read (jsonOptions : JsonSerializerOptions) cancellationToken (reader : MultipartReader) = task {
151+
let mutable section : GraphQLMultipartSection voption = ValueNone
152+
let readNextSection () = task {
153+
let! next = reader.ReadNextSectionAsync cancellationToken
154+
section <- GraphQLMultipartSection.FromSection (next)
155+
}
156+
let mutable operations : string = null
157+
let mutable map : IDictionary<string, string> = null
158+
let files = Dictionary<string, File> ()
159+
do! readNextSection ()
160+
while not section.IsNone do
161+
match section.Value with
162+
| Form section ->
163+
let! value = section.GetValueAsync ()
164+
match section.Name with
165+
| "operations" -> operations <- value
166+
| "map" ->
167+
map <-
168+
JsonSerializer.Deserialize<Map<string, string list>> (value, jsonOptions)
169+
|> Seq.map (fun kvp -> kvp.Value.Head, kvp.Key)
170+
|> Map.ofSeq
171+
| _ -> failwithf $"""Error reading multipart request. Unexpected section name "%s{section.Name}"."""
172+
| File section ->
173+
let stream = new System.IO.MemoryStream (4096)
174+
do! section.FileStream.CopyToAsync (stream, cancellationToken)
175+
stream.Position <- 0L
176+
let value = {
177+
Name = section.FileName
178+
ContentType = section.Section.ContentType
179+
Content = stream
134180
}
135-
let mutable operations : string = null
136-
let mutable map : IDictionary<string, string> = null
137-
let files = Dictionary<string, File>()
181+
files.Add (section.Name, value)
138182
do! readNextSection ()
139-
while not section.IsNone do
140-
match section.Value with
141-
| Form section ->
142-
let! value = section.GetValueAsync()
143-
match section.Name with
144-
| "operations" ->
145-
operations <- value
146-
| "map" ->
147-
map <- JsonSerializer.Deserialize<Map<string, string list>>(value, jsonOptions)
148-
|> Seq.map (fun kvp -> kvp.Value.Head, kvp.Key)
149-
|> Map.ofSeq
150-
| _ -> failwithf $"""Error reading multipart request. Unexpected section name "%s{section.Name}"."""
151-
| File section ->
152-
let stream = new System.IO.MemoryStream(4096)
153-
do! section.FileStream.CopyToAsync(stream, cancellationToken)
154-
stream.Position <- 0L
155-
let value = { Name = section.FileName; ContentType = section.Section.ContentType; Content = stream }
156-
files.Add(section.Name, value)
157-
do! readNextSection ()
158-
let operations =
159-
let jsonElement = (JsonDocument.Parse operations).RootElement
160-
match jsonElement.ValueKind with
161-
| JsonValueKind.Array -> jsonElement.Deserialize<GQLRequestContent list>(jsonOptions)
162-
| JsonValueKind.Object -> [ jsonElement.Deserialize<GQLRequestContent>(jsonOptions) ]
163-
| _ -> failwith "Unexpected operations value."
164-
return { Operations = parseOperations jsonOptions operations map files }
165-
}
183+
let operations =
184+
let jsonElement = (JsonDocument.Parse operations).RootElement
185+
match jsonElement.ValueKind with
186+
| JsonValueKind.Array -> jsonElement.Deserialize<GQLRequestContent list> (jsonOptions)
187+
| JsonValueKind.Object -> [ jsonElement.Deserialize<GQLRequestContent> (jsonOptions) ]
188+
| _ -> failwith "Unexpected operations value."
189+
return { Operations = parseOperations jsonOptions operations map files }
190+
}

samples/star-wars-api/Policies.fs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ module Policies =
99
let [<Literal>] Dummy = "Dummy"
1010
let [<Literal>] CanSetMoon = "CanSetMoon"
1111

12-
type DummyRequirement () = interface IAuthorizationRequirement
12+
type DummyRequirement () =
13+
interface IAuthorizationRequirement
1314

1415
type DummyHandler () =
1516

@@ -28,11 +29,14 @@ type IsCharacterHandler () =
2829
inherit AuthorizationHandler<IsCharacterRequirement> () // Inject services from DI
2930

3031
override _.HandleRequirementAsync (context, requirement) =
31-
Async.StartImmediateAsTask(async {
32+
Async.StartImmediateAsTask (async {
3233
let allowedCharacters = requirement.Characters
33-
if context.User.Claims
34+
if
35+
context.User.Claims
3436
|> Seq.where (fun c -> c.Type = "character")
3537
|> Seq.exists (fun c -> allowedCharacters |> Set.contains c.Value)
36-
then context.Succeed requirement
37-
else () // Go to the next handler if registered
38+
then
39+
context.Succeed requirement
40+
else
41+
() // Go to the next handler if registered
3842
}) :> _

samples/star-wars-api/Program.fs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ open Microsoft.Extensions.Configuration
66

77
let exitCode = 0
88

9-
let buildWebHost (args: string array) =
9+
let buildWebHost (args : string array) =
1010

1111
// Build an initial configuration that takes in both environment and command line settings.
1212
let config = ConfigurationBuilder()
@@ -16,18 +16,18 @@ let buildWebHost (args: string array) =
1616

1717
// This is done so that an environment specified on the command line with "--environment" is respected,
1818
// when we look for appsettings.*.json files.
19-
let configureAppConfiguration (context: WebHostBuilderContext) (config: IConfigurationBuilder) =
19+
let configureAppConfiguration (context : WebHostBuilderContext) (config : IConfigurationBuilder) =
2020

2121
// The default IFileProvider has the working directory set to the same as the DLL.
2222
// We'll use this to re-set the FileProvider in the configuration builder below.
23-
let fileProvider = ConfigurationBuilder().GetFileProvider()
23+
let fileProvider = ConfigurationBuilder().GetFileProvider ()
2424

2525
// Extract the environment name from the configuration that was already built above
2626
let envName = context.HostingEnvironment.EnvironmentName
2727
// Use the name to find the additional appsettings file, if present.
2828
config.SetFileProvider(fileProvider)
29-
.AddJsonFile("appsettings.json", false, true)
30-
.AddJsonFile($"appsettings.{envName}.json", true) |> ignore
29+
.AddJsonFile("appsettings.json", false, true)
30+
.AddJsonFile($"appsettings.{envName}.json", true) |> ignore
3131

3232
WebHost
3333
.CreateDefaultBuilder(args)
@@ -37,5 +37,5 @@ let buildWebHost (args: string array) =
3737

3838
[<EntryPoint>]
3939
let main args =
40-
buildWebHost(args).Build().Run()
40+
buildWebHost(args).Build().Run ()
4141
exitCode

samples/star-wars-api/Root.fs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ open System
44
open Microsoft.AspNetCore.Http
55
open Microsoft.Extensions.DependencyInjection
66

7-
type Root(ctx : HttpContext) =
7+
type Root (ctx : HttpContext) =
88

99
member _.RequestId = ctx.TraceIdentifier
10-
member _.RequestAborted: System.Threading.CancellationToken = ctx.RequestAborted
11-
member _.ServiceProvider: IServiceProvider = ctx.RequestServices
12-
member root.GetRequiredService<'t>() = root.ServiceProvider.GetRequiredService<'t>()
10+
member _.RequestAborted : System.Threading.CancellationToken = ctx.RequestAborted
11+
member _.ServiceProvider : IServiceProvider = ctx.RequestServices
12+
member root.GetRequiredService<'t> () = root.ServiceProvider.GetRequiredService<'t> ()

0 commit comments

Comments
 (0)