Skip to content

Commit ee7f640

Browse files
Andrew-Lees11djones6
authored andcommitted
Support Swift 5 (#128)
* Swift 5 language changes * Update Swift-Kuery-ORM to 0.5.0 * Update to Kitura-WebSocket-NIO instead of branch * Update to Swift 5.0.1
1 parent 3081cf8 commit ee7f640

File tree

6 files changed

+223
-81
lines changed

6 files changed

+223
-81
lines changed

.swift-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
4.2.3
1+
5.0.1

.travis.yml

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ branches:
1212
matrix:
1313
include:
1414
- os: linux
15+
# Trusty build retained to provide 14.04 coverage (as paid support is still available)
1516
dist: trusty
1617
sudo: required
1718
env: SWIFT_SNAPSHOT=4.0.3
@@ -24,24 +25,30 @@ matrix:
2425
dist: xenial
2526
sudo: required
2627
services: docker
27-
env: DOCKER_IMAGE=swift:4.2.3
28-
# Temporarily disabled: appid-serversdk-swift does not yet compile on Swift 5
29-
# https://github.com/ibm-cloud-security/appid-serversdk-swift/issues/83
30-
# - os: linux
31-
# dist: xenial
32-
# sudo: required
33-
# services: docker
34-
# env: DOCKER_IMAGE=swift:4.2.3 SWIFT_SNAPSHOT=$SWIFT_DEVELOPMENT_SNAPSHOT
28+
env: DOCKER_IMAGE=swift:4.2.4 SWIFT_SNAPSHOT=4.2.4
3529
- os: linux
3630
dist: xenial
3731
sudo: required
3832
services: docker
39-
env: DOCKER_IMAGE=swift:4.2.3 KITURA_NIO=1
33+
# Note: Ubuntu 16.04
34+
env: DOCKER_IMAGE=swift:5.0.1-xenial
4035
- os: linux
4136
dist: xenial
4237
sudo: required
4338
services: docker
44-
env: DOCKER_IMAGE=ubuntu:18.04 KITURA_NIO=1
39+
# Note: Kitura-WebSocket-NIO requires zlib
40+
env: DOCKER_IMAGE=swift:5.0.1-xenial KITURA_NIO=1 DOCKER_PACKAGES="libz-dev"
41+
- os: linux
42+
dist: xenial
43+
sudo: required
44+
services: docker
45+
# Note: Ubuntu 18.04
46+
env: DOCKER_IMAGE=swift:5.0.1 SWIFT_SNAPSHOT=$SWIFT_DEVELOPMENT_SNAPSHOT
47+
- os: linux
48+
dist: xenial
49+
sudo: required
50+
services: docker
51+
env: DOCKER_IMAGE=swift:5.0.1 SWIFT_SNAPSHOT=$SWIFT_DEVELOPMENT_SNAPSHOT KITURA_NIO=1 DOCKER_PACKAGES="libz-dev"
4552
- os: osx
4653
osx_image: xcode9.2
4754
sudo: required
@@ -53,10 +60,22 @@ matrix:
5360
- os: osx
5461
osx_image: xcode10.1
5562
sudo: required
63+
env: SWIFT_SNAPSHOT=4.2.1
5664
- os: osx
57-
osx_image: xcode10.1
65+
osx_image: xcode10.2
66+
sudo: required
67+
- os: osx
68+
osx_image: xcode10.2
69+
sudo: required
70+
env: KITURA_NIO=1
71+
- os: osx
72+
osx_image: xcode10.2
5873
sudo: required
5974
env: SWIFT_SNAPSHOT=$SWIFT_DEVELOPMENT_SNAPSHOT
75+
- os: osx
76+
osx_image: xcode10.2
77+
sudo: required
78+
env: SWIFT_SNAPSHOT=$SWIFT_DEVELOPMENT_SNAPSHOT KITURA_NIO=1
6079

6180
before_install:
6281
- git clone https://github.com/IBM-Swift/Package-Builder.git

Package.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
// swift-tools-version:4.0
1+
// swift-tools-version:5.0
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
/**
5-
* Copyright IBM Corporation 2016, 2017
5+
* Copyright IBM Corporation 2016, 2017, 2019
66
*
77
* Licensed under the Apache License, Version 2.0 (the "License");
88
* you may not use this file except in compliance with the License.
@@ -21,9 +21,9 @@ import PackageDescription
2121
import Foundation
2222

2323
var dependencies: [Package.Dependency] = [
24-
.package(url: "https://github.com/IBM-Swift/Kitura.git", from: "2.5.0"),
24+
.package(url: "https://github.com/IBM-Swift/Kitura.git", from: "2.6.0"),
2525
.package(url: "https://github.com/IBM-Swift/HeliumLogger.git", from: "1.7.1"),
26-
.package(url: "https://github.com/IBM-Swift/CloudEnvironment.git", from: "8.0.0"),
26+
.package(url: "https://github.com/IBM-Swift/CloudEnvironment.git", from: "9.0.0"),
2727
.package(url: "https://github.com/RuntimeTools/SwiftMetrics.git", from: "2.5.0"),
2828
.package(url: "https://github.com/IBM-Swift/Health.git", from: "1.0.0"),
2929
.package(url: "https://github.com/IBM-Swift/Kitura-OpenAPI.git", from: "1.1.0"),
@@ -34,7 +34,7 @@ var dependencies: [Package.Dependency] = [
3434
.package(url: "https://github.com/IBM-Swift/Kitura-CredentialsGoogle.git", from: "2.2.0"),
3535
.package(url: "https://github.com/IBM-Swift/Kitura-CredentialsFacebook.git", from: "2.2.0"),
3636
.package(url: "https://github.com/IBM-Swift/Swift-JWT", from: "3.0.0"),
37-
.package(url: "https://github.com/IBM-Swift/Swift-Kuery-ORM.git", .upToNextMinor(from: "0.3.1")),
37+
.package(url: "https://github.com/IBM-Swift/Swift-Kuery-ORM.git", .upToNextMinor(from: "0.5.0")),
3838
]
3939
var targetDependencies: [Target.Dependency] = [ "Kitura", "CloudEnvironment","SwiftMetrics","Health", "KituraOpenAPI", "KituraMarkdown", "KituraStencil", "CredentialsHTTP", "KituraSession", "CredentialsGoogle", "CredentialsFacebook", "SwiftJWT", "SwiftKueryORM",
4040
]
@@ -49,9 +49,9 @@ dependencies.append(.package(url: "https://github.com/ibm-cloud-security/appid-s
4949
targetDependencies.append("IBMCloudAppID")
5050
#endif
5151

52-
// Temporarily use alternate branch of Kitura-WebSocket while building in NIO mode
52+
// Use alternate implementation of Kitura-WebSocket while building in NIO mode
5353
if ProcessInfo.processInfo.environment["KITURA_NIO"] != nil {
54-
dependencies.append(.package(url: "https://github.com/IBM-Swift/Kitura-WebSocket.git", .exact("0.1.0-nio")))
54+
dependencies.append(.package(url: "https://github.com/IBM-Swift/Kitura-WebSocket-NIO.git", from: "2.0.0"))
5555
} else {
5656
dependencies.append(.package(url: "https://github.com/IBM-Swift/Kitura-WebSocket.git", from: "2.0.0"))
5757
}

[email protected]

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// swift-tools-version:4.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
/**
5+
* Copyright IBM Corporation 2016, 2017, 2019
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
**/
19+
20+
import PackageDescription
21+
import Foundation
22+
23+
var dependencies: [Package.Dependency] = [
24+
.package(url: "https://github.com/IBM-Swift/Kitura.git", .upToNextMinor(from: "2.6.0")),
25+
.package(url: "https://github.com/IBM-Swift/HeliumLogger.git", from: "1.7.1"),
26+
.package(url: "https://github.com/IBM-Swift/CloudEnvironment.git", from: "9.0.0"),
27+
.package(url: "https://github.com/RuntimeTools/SwiftMetrics.git", from: "2.5.0"),
28+
.package(url: "https://github.com/IBM-Swift/Health.git", from: "1.0.0"),
29+
.package(url: "https://github.com/IBM-Swift/Kitura-OpenAPI.git", from: "1.1.0"),
30+
.package(url: "https://github.com/IBM-Swift/Kitura-StencilTemplateEngine.git", from: "1.9.0"),
31+
.package(url: "https://github.com/IBM-Swift/Kitura-Markdown.git", from: "1.0.0"),
32+
.package(url: "https://github.com/IBM-Swift/Kitura-CredentialsHTTP.git", from: "2.1.0"),
33+
.package(url: "https://github.com/IBM-Swift/Kitura-Session.git", from: "3.3.0"),
34+
.package(url: "https://github.com/IBM-Swift/Kitura-CredentialsGoogle.git", from: "2.2.0"),
35+
.package(url: "https://github.com/IBM-Swift/Kitura-CredentialsFacebook.git", from: "2.2.0"),
36+
.package(url: "https://github.com/IBM-Swift/Swift-JWT", from: "3.0.0"),
37+
.package(url: "https://github.com/IBM-Swift/Swift-Kuery-ORM.git", .upToNextMinor(from: "0.5.0")),
38+
]
39+
var targetDependencies: [Target.Dependency] = [ "Kitura", "CloudEnvironment","SwiftMetrics","Health", "KituraOpenAPI", "KituraMarkdown", "KituraStencil", "CredentialsHTTP", "KituraSession", "CredentialsGoogle", "CredentialsFacebook", "SwiftJWT", "SwiftKueryORM",
40+
]
41+
42+
// Uncomment to use PostgreSQL
43+
// dependencies.append(.package(url: "https://github.com/IBM-Swift/Swift-Kuery-PostgreSQL.git", from: "1.2.0"))
44+
// targetDependencies.append("SwiftKueryPostgreSQL")
45+
46+
// IBMCloudAppID requires OpenSSL that is not included on Mac by default.
47+
#if os(Linux)
48+
dependencies.append(.package(url: "https://github.com/ibm-cloud-security/appid-serversdk-swift", .branch("development")))
49+
targetDependencies.append("IBMCloudAppID")
50+
#endif
51+
52+
// Use alternate implementation of Kitura-WebSocket while building in NIO mode
53+
if ProcessInfo.processInfo.environment["KITURA_NIO"] != nil {
54+
dependencies.append(.package(url: "https://github.com/IBM-Swift/Kitura-WebSocket-NIO.git", from: "1.0.0"))
55+
} else {
56+
dependencies.append(.package(url: "https://github.com/IBM-Swift/Kitura-WebSocket.git", from: "2.0.0"))
57+
}
58+
59+
let package = Package(
60+
name: "Kitura-Sample",
61+
dependencies: dependencies,
62+
targets: [
63+
.target(name: "Kitura-Sample", dependencies: [ .target(name: "Application"), .target(name: "ChatService"), "Kitura" , "HeliumLogger"]),
64+
.target(name: "Application", dependencies: targetDependencies),
65+
.target(name: "ChatService", dependencies: ["Kitura-WebSocket"]),
66+
.testTarget(name: "KituraSampleRouterTests" , dependencies: [.target(name: "Application"), "Kitura","HeliumLogger" ])
67+
]
68+
)

Sources/Application/DummyDatabase.swift

Lines changed: 77 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,23 @@ import SwiftKuery
2020
// This class is a dummy SwiftKuery plugin that allows the saving and retrieval of "Grade" objects in local storage.
2121
// This allows the Database example to run prior to connecting to a real database.
2222
class DummyConnection: Connection {
23-
var grades = [Grade]()
24-
let queryBuilder: QueryBuilder
25-
26-
init(withDeleteRequiresUsing: Bool = false, withUpdateRequiresFrom: Bool = false, createAutoIncrement: ((String, Bool) -> String)? = nil) {
27-
self.queryBuilder = QueryBuilder(withDeleteRequiresUsing: withDeleteRequiresUsing, withUpdateRequiresFrom: withUpdateRequiresFrom, createAutoIncrement: createAutoIncrement)
23+
func execute(preparedStatement: PreparedStatement, parameters: [String : Any?], onCompletion: @escaping ((QueryResult) -> ())) {
24+
onCompletion(.successNoData)
2825
}
2926

30-
func connect(onCompletion: (QueryError?) -> ()) {}
31-
32-
public var isConnected: Bool { return true }
33-
34-
func closeConnection() {}
27+
var grades = [Grade]()
3528

3629
func execute(query: Query, onCompletion: @escaping ((QueryResult) -> ())) {
3730
do {
3831
let queryComponents = (try query.build(queryBuilder: queryBuilder)).components(separatedBy: " ")
3932
switch queryComponents[0] {
4033
case "SELECT":
4134
if queryComponents[1] == "*" {
42-
return onCompletion(.resultSet(ResultSet(DummyResultFetcher(grades: grades))))
35+
if grades.isEmpty {
36+
return onCompletion(.successNoData)
37+
} else {
38+
return onCompletion(QueryResult.resultSet(ResultSet(DummyResultFetcher(grades: grades), connection: self)))
39+
}
4340
}
4441
case "DELETE":
4542
grades = []
@@ -64,7 +61,7 @@ class DummyConnection: Connection {
6461
case "SELECT":
6562
if let course = parameters[0] as? String {
6663
let matchingGrades = grades.filter { $0.course == course }
67-
return onCompletion(.resultSet(ResultSet(DummyResultFetcher(grades: matchingGrades))))
64+
return onCompletion(.resultSet(ResultSet(DummyResultFetcher(grades: matchingGrades), connection: self)))
6865
}
6966
default:
7067
return onCompletion(QueryResult.successNoData)
@@ -94,35 +91,45 @@ class DummyConnection: Connection {
9491
return (try? query.build(queryBuilder: queryBuilder)) ?? ""
9592
}
9693

97-
private func returnResult(_ onCompletion: @escaping ((QueryResult) -> ())) {
98-
return onCompletion(.successNoData)
94+
func execute(preparedStatement: PreparedStatement, parameters: [Any?], onCompletion: @escaping ((QueryResult) -> ())) {
95+
onCompletion(.successNoData)
9996
}
10097

101-
func startTransaction(onCompletion: @escaping ((QueryResult) -> ())) {}
98+
func execute(preparedStatement: PreparedStatement, onCompletion: @escaping ((QueryResult) -> ())) {
99+
onCompletion(.successNoData)
100+
}
102101

103-
func commit(onCompletion: @escaping ((QueryResult) -> ())) {}
102+
init(withDeleteRequiresUsing: Bool = false, withUpdateRequiresFrom: Bool = false) {
103+
self.queryBuilder = QueryBuilder(columnBuilder: DummySQLColumnBuilder())
104+
}
104105

105-
func rollback(onCompletion: @escaping ((QueryResult) -> ())) {}
106+
var queryBuilder: QueryBuilder
106107

107-
func create(savepoint: String, onCompletion: @escaping ((QueryResult) -> ())) {}
108+
func connect(onCompletion: @escaping (QueryResult) -> ()) {}
108109

109-
func rollback(to savepoint: String, onCompletion: @escaping ((QueryResult) -> ())) {}
110+
func connectSync() -> QueryResult { return QueryResult.successNoData }
111+
func closeConnection() {}
110112

111-
func release(savepoint: String, onCompletion: @escaping ((QueryResult) -> ())) {}
113+
var isConnected: Bool = true
114+
115+
func prepareStatement(_ query: Query, onCompletion: @escaping ((QueryResult) -> ())) {}
116+
117+
func prepareStatement(_ raw: String, onCompletion: @escaping ((QueryResult) -> ())) {}
112118

113-
struct TestPreparedStatement: PreparedStatement {}
119+
func release(preparedStatement: PreparedStatement, onCompletion: @escaping ((QueryResult) -> ())) {}
120+
121+
func startTransaction(onCompletion: @escaping ((QueryResult) -> ())) { }
114122

115-
func prepareStatement(_ query: Query) throws -> PreparedStatement { return TestPreparedStatement() }
123+
func commit(onCompletion: @escaping ((QueryResult) -> ())) {}
116124

117-
func prepareStatement(_ raw: String) throws -> PreparedStatement { return TestPreparedStatement() }
125+
func rollback(onCompletion: @escaping ((QueryResult) -> ())) {}
118126

119-
func execute(preparedStatement: PreparedStatement, onCompletion: @escaping ((QueryResult) -> ())) {}
127+
func create(savepoint: String, onCompletion: @escaping ((QueryResult) -> ())) {}
120128

121-
func execute(preparedStatement: PreparedStatement, parameters: [Any?], onCompletion: @escaping ((QueryResult) -> ())) {}
129+
func rollback(to savepoint: String, onCompletion: @escaping ((QueryResult) -> ())) {}
122130

123-
func execute(preparedStatement: PreparedStatement, parameters: [String:Any?], onCompletion: @escaping ((QueryResult) -> ())) {}
131+
func release(savepoint: String, onCompletion: @escaping ((QueryResult) -> ())) {}
124132

125-
func release(preparedStatement: PreparedStatement, onCompletion: @escaping ((QueryResult) -> ())) {}
126133
}
127134

128135
class DummyResultFetcher: ResultFetcher {
@@ -138,19 +145,55 @@ class DummyResultFetcher: ResultFetcher {
138145
}
139146
}
140147

141-
func fetchNext() -> [Any?]? {
148+
func fetchNext(callback: @escaping (([Any?]?, Error?)) -> ()) {
142149
if fetched < numberOfRows {
143150
fetched += 1
144-
return rows[fetched - 1]
151+
callback((rows[fetched - 1], nil))
145152
}
146-
return nil
153+
callback((nil, nil))
147154
}
148155

149-
func fetchNext(callback: ([Any?]?) ->()) {
150-
callback(fetchNext())
156+
func fetchTitles(callback: @escaping (([String]?, Error?)) -> ()) {
157+
callback((titles, nil))
151158
}
152159

153-
func fetchTitles() -> [String] {
154-
return titles
160+
func done() {}
161+
}
162+
163+
class DummySQLColumnBuilder: ColumnCreator {
164+
func buildColumn(for column: Column, using queryBuilder: QueryBuilder) -> String? {
165+
guard let type = column.type else {
166+
return nil
167+
}
168+
169+
var result = column.name
170+
let identifierQuoteCharacter = queryBuilder.substitutions[QueryBuilder.QuerySubstitutionNames.identifierQuoteCharacter.rawValue]
171+
if !result.hasPrefix(identifierQuoteCharacter) {
172+
result = identifierQuoteCharacter + result + identifierQuoteCharacter + " "
173+
}
174+
175+
var typeString = type.create(queryBuilder: queryBuilder)
176+
if let length = column.length {
177+
typeString += "(\(length))"
178+
}
179+
180+
if column.isPrimaryKey {
181+
result += " PRIMARY KEY"
182+
}
183+
if column.isNotNullable {
184+
result += " NOT NULL"
185+
}
186+
if column.isUnique {
187+
result += " UNIQUE"
188+
}
189+
if let checkExpression = column.checkExpression {
190+
result += checkExpression.contains(column.name) ? " CHECK (" + checkExpression.replacingOccurrences(of: column.name, with: "\"\(column.name)\"") + ")" : " CHECK (" + checkExpression + ")"
191+
}
192+
if let collate = column.collate {
193+
result += " COLLATE \"" + collate + "\""
194+
}
195+
return result
155196
}
197+
198+
156199
}

0 commit comments

Comments
 (0)