GraphQL data structure implemented in Swift
import Foundation | |
protocol GQLNodeArgument {} | |
extension String: GQLNodeArgument {} | |
extension NSNumber: GQLNodeArgument {} | |
class GQLNode: StringLiteralConvertible, ArrayLiteralConvertible, Printable, DebugPrintable { | |
let name: String? | |
let arguments: [String : GQLNodeArgument] | |
let properties: [GQLNode] | |
var isRootNode: Bool { | |
return self.name?.isEmpty ?? true | |
} | |
init(name: String, arguments: [String : GQLNodeArgument] = [:], properties: [GQLNode] = []) { | |
for node in properties { | |
assert(!node.isRootNode, "You cannot include a root node, or a node with an empty name as a child of another node.") | |
} | |
self.name = name | |
self.arguments = arguments | |
self.properties = properties | |
} | |
required convenience init(stringLiteral value: StringLiteralType) { | |
self.init(name: value) | |
} | |
required convenience init(extendedGraphemeClusterLiteral value: StringLiteralType) { | |
self.init(name: value) | |
} | |
required convenience init(unicodeScalarLiteral value: StringLiteralType) { | |
self.init(name: value) | |
} | |
required convenience init(arrayLiteral elements: GQLNode...) { | |
self.init(name: "", properties: elements) | |
} | |
func render(pretty: Bool = false, indentationLevel: Int = 0) -> String { | |
var rendered: String = "" | |
let indentationText: String | |
if pretty { | |
indentationText = "".join(Array(count: indentationLevel, repeatedValue: " ")) | |
} else { | |
indentationText = "" | |
} | |
rendered += indentationText | |
if let name = self.name { | |
rendered += name | |
} | |
if self.arguments.count > 0 { | |
rendered += "(" | |
var argumentTexts: [String] = [] | |
for (name, argument) in self.arguments { | |
argumentTexts.append("\(name): \(argument)") | |
} | |
rendered += ", ".join(argumentTexts) | |
if pretty { | |
rendered += ") " | |
} else { | |
rendered += ")" | |
} | |
} | |
if self.properties.count > 0 { | |
rendered += "{" | |
if pretty { | |
rendered += "\n" | |
} | |
var propertyTexts: [String] = [] | |
for property in self.properties { | |
propertyTexts.append(property.render(pretty: pretty, indentationLevel: indentationLevel + 1)) | |
} | |
if pretty { | |
rendered += ",\n".join(propertyTexts) | |
} else { | |
rendered += ",".join(propertyTexts) | |
} | |
if pretty { | |
rendered += "\n" | |
} | |
rendered += indentationText + "}" | |
} | |
return rendered | |
} | |
var description: String { | |
return self.render(pretty: true) | |
} | |
var debugDescription: String { | |
return "GQLNode(\(self.render(pretty: true)))" | |
} | |
} | |
let query: GQLNode = [ | |
GQLNode(name: "user", arguments: ["id" : 3500401], properties: [ | |
"id", | |
"name", | |
"isViewerFriend", | |
GQLNode(name: "profilePicture", arguments: ["size" : 50], properties: [ | |
"uri", | |
"width", | |
"height", | |
]), | |
]) | |
] | |
query.render(pretty: true) | |
query.render(pretty: false) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment