-
-
Save vsouza/4368660c75268c87d42a to your computer and use it in GitHub Desktop.
GraphQL data structure implemented in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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