main.swift 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * Copyright 2017, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import Foundation
  17. import gRPC
  18. import OAuth2
  19. import Commander
  20. let projectID = "your-project-identifier"
  21. let scopes = ["https://www.googleapis.com/auth/datastore"]
  22. struct Thing : Codable {
  23. var name: String
  24. var number: Int
  25. }
  26. class PropertiesEncoder {
  27. static func encode<T : Encodable>(_ value : T) throws -> [String:Any]? {
  28. let plist = try PropertyListEncoder().encode(value)
  29. let properties = try PropertyListSerialization.propertyList(from:plist, options:[], format:nil)
  30. return properties as? [String:Any]
  31. }
  32. }
  33. class PropertiesDecoder {
  34. static func decode<T: Decodable>(_ type: T.Type, from: [String:Any]) throws -> T {
  35. let plist = try PropertyListSerialization.data(fromPropertyList: from,
  36. format: .binary, options:0)
  37. return try PropertyListDecoder().decode(type, from: plist)
  38. }
  39. }
  40. func runSelectQuery(service: Google_Datastore_V1_DatastoreService) throws {
  41. var request = Google_Datastore_V1_RunQueryRequest()
  42. request.projectID = projectID
  43. var query = Google_Datastore_V1_GqlQuery()
  44. query.queryString = "select * from Thing"
  45. request.gqlQuery = query
  46. let result = try service.runquery(request)
  47. var entities : [Thing] = []
  48. for entityResult in result.batch.entityResults {
  49. var properties : [String:Any] = [:]
  50. for property in entityResult.entity.properties {
  51. let key = property.key
  52. switch property.value.valueType! {
  53. case .integerValue(let v):
  54. properties[key] = v
  55. case .stringValue(let v):
  56. properties[key] = v
  57. default:
  58. print("?")
  59. }
  60. }
  61. let entity = try PropertiesDecoder.decode(Thing.self, from:properties)
  62. entities.append(entity)
  63. }
  64. print("\(entities)")
  65. }
  66. func runInsert(service: Google_Datastore_V1_DatastoreService,
  67. number: Int) throws {
  68. var request = Google_Datastore_V1_CommitRequest()
  69. request.projectID = projectID
  70. request.mode = .nonTransactional
  71. var pathElement = Google_Datastore_V1_Key.PathElement()
  72. pathElement.kind = "Thing"
  73. var key = Google_Datastore_V1_Key()
  74. key.path = [pathElement]
  75. var entity = Google_Datastore_V1_Entity()
  76. entity.key = key
  77. let thing = Thing(name:"Thing", number:number)
  78. let properties = try PropertiesEncoder.encode(thing)!
  79. for (k,v) in properties {
  80. var value = Google_Datastore_V1_Value()
  81. switch v {
  82. case let v as String:
  83. value.stringValue = v
  84. case let v as Int:
  85. value.integerValue = Int64(v)
  86. default:
  87. break
  88. }
  89. entity.properties[k] = value
  90. }
  91. var mutation = Google_Datastore_V1_Mutation()
  92. mutation.insert = entity
  93. request.mutations.append(mutation)
  94. let result = try service.commit(request)
  95. for mutationResult in result.mutationResults {
  96. print("\(mutationResult)")
  97. }
  98. }
  99. func runDelete(service: Google_Datastore_V1_DatastoreService,
  100. kind: String,
  101. id: Int64) throws {
  102. var request = Google_Datastore_V1_CommitRequest()
  103. request.projectID = projectID
  104. request.mode = .nonTransactional
  105. var pathElement = Google_Datastore_V1_Key.PathElement()
  106. pathElement.kind = kind
  107. pathElement.id = id
  108. var key = Google_Datastore_V1_Key()
  109. key.path = [pathElement]
  110. var mutation = Google_Datastore_V1_Mutation()
  111. mutation.delete = key
  112. request.mutations.append(mutation)
  113. let result = try service.commit(request)
  114. for mutationResult in result.mutationResults {
  115. print("\(mutationResult)")
  116. }
  117. }
  118. func prepareService() throws -> Google_Datastore_V1_DatastoreService? {
  119. // Get an OAuth token
  120. var authToken : String!
  121. if let provider = DefaultTokenProvider(scopes:scopes) {
  122. let sem = DispatchSemaphore(value: 0)
  123. try provider.withToken() {(token, error) -> Void in
  124. if let token = token {
  125. authToken = token.AccessToken
  126. }
  127. sem.signal()
  128. }
  129. sem.wait()
  130. }
  131. if authToken == nil {
  132. print("ERROR: No OAuth token is available. Did you set GOOGLE_APPLICATION_CREDENTIALS?")
  133. exit(-1)
  134. }
  135. // Initialize gRPC service
  136. gRPC.initialize()
  137. let certificateURL = URL(fileURLWithPath:"/roots.pem")
  138. let certificates = try! String(contentsOf: certificateURL, encoding: .utf8)
  139. let service = Google_Datastore_V1_DatastoreService(address:"datastore.googleapis.com",
  140. certificates:certificates,
  141. host:nil)
  142. service.metadata = Metadata(["authorization":"Bearer " + authToken])
  143. return service
  144. }
  145. Group {
  146. $0.command("insert") { (number:Int) in
  147. if let service = try prepareService() {
  148. try runInsert(service:service, number:number)
  149. }
  150. }
  151. $0.command("delete") { (id:Int) in
  152. if let service = try prepareService() {
  153. try runDelete(service:service, kind:"Thing", id:Int64(id))
  154. }
  155. }
  156. $0.command("query") {
  157. if let service = try prepareService() {
  158. try runSelectQuery(service:service)
  159. }
  160. }
  161. }.run()