Skip to content

Commit ac4df1f

Browse files
committed
Add CI for Functions Codable and address review feedback
1 parent ee57ffe commit ac4df1f

File tree

13 files changed

+312
-274
lines changed

13 files changed

+312
-274
lines changed

.github/workflows/functions.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,13 @@ jobs:
4646
- name: Initialize xcodebuild
4747
run: scripts/setup_spm_tests.sh
4848
- name: iOS Unit Tests
49-
run: scripts/third_party/travis/retry.sh ./scripts/build.sh FirebaseFunctions iOS spmbuildonly
49+
run: scripts/third_party/travis/retry.sh ./scripts/build.sh FunctionsUnit iOS spm
5050
- name: Integration Test Server
5151
run: FirebaseFunctions/Backend/start.sh synchronous
52-
- name: iOS Swift Integration Tests
52+
- name: iOS Swift Integration Tests (Objective C library)
5353
run: scripts/third_party/travis/retry.sh ./scripts/build.sh FunctionsSwiftIntegration iOS spm
54+
- name: iOS Swift Integration Tests (including Swift library)
55+
run: scripts/third_party/travis/retry.sh ./scripts/build.sh FirebaseFunctionsSwiftUnit iOS spm
5456
- name: iOS Objective C Integration Tests
5557
run: scripts/third_party/travis/retry.sh ./scripts/build.sh FunctionsIntegration iOS spm
5658
- name: Combine Unit Tests
@@ -68,7 +70,7 @@ jobs:
6870
- name: Initialize xcodebuild
6971
run: scripts/setup_spm_tests.sh
7072
- name: Unit Tests
71-
run: scripts/third_party/travis/retry.sh ./scripts/build.sh FirebaseFunctions ${{ matrix.target }} spmbuildonly
73+
run: scripts/third_party/travis/retry.sh ./scripts/build.sh FunctionsUnit ${{ matrix.target }} spm
7274

7375
catalyst:
7476
# Don't run on private repo unless it is a PR.

FirebaseDatabaseSwift/Sources/Codable/EncoderDecoder.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ import FirebaseDatabase
1818
import FirebaseSharedSwift
1919

2020
extension Database {
21-
public typealias Encoder = StructureEncoder
22-
public typealias Decoder = StructureDecoder
21+
public typealias Encoder = FirebaseDataEncoder
22+
public typealias Decoder = FirebaseDataDecoder
2323
}

FirebaseDatabaseSwift/Tests/Codable/ServerValueCodingTests.swift

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,4 @@ class DictionarySubject {
188188
XCTFail("Failed to decode \(X.self): \(error)", file: file, line: line)
189189
}
190190
}
191-
192-
func failsDecoding<X: Equatable & Codable>(to _: X.Type,
193-
using decoder: Database.Decoder = .init()) -> Void {
194-
XCTAssertThrowsError(
195-
try decoder.decode(X.self, from: subject),
196-
file: file,
197-
line: line
198-
)
199-
}
200191
}

FirebaseFunctionsSwift/Sources/Codable/Callable+Codable.swift

Lines changed: 101 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,41 @@
1-
/*
2-
* Copyright 2020 Google LLC
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-
*/
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
1614

1715
import Foundation
1816
import FirebaseFunctions
1917
import FirebaseSharedSwift
2018

2119
public extension Functions {
22-
/**
23-
* Creates a reference to the Callable HTTPS trigger with the given name, the type of an `Encodable`
24-
* request and the type of a `Decodable` response.
25-
*
26-
* - Parameter name: The name of the Callable HTTPS trigger
27-
* - Parameter requestType: The type of the `Encodable` entity to use for requests to this `Callable`
28-
* - Parameter responseType: The type of the `Decodable` entity to use for responses from this `Callable`
29-
*/
20+
/// Creates a reference to the Callable HTTPS trigger with the given name, the type of an `Encodable`
21+
/// request and the type of a `Decodable` response.
22+
/// - Parameter name: The name of the Callable HTTPS trigger
23+
/// - Parameter requestType: The type of the `Encodable` entity to use for requests to this `Callable`
24+
/// - Parameter responseType: The type of the `Decodable` entity to use for responses from this `Callable`
3025
func httpsCallable<Request: Encodable,
3126
Response: Decodable>(_ name: String,
32-
requestType: Request.Type,
33-
responseType: Response.Type,
34-
encoder: StructureEncoder = StructureEncoder(),
35-
decoder: StructureDecoder = StructureDecoder())
27+
requestAs requestType: Request.Type = Request.self,
28+
responseAs responseType: Response.Type = Response.self,
29+
encoder: FirebaseDataEncoder = FirebaseDataEncoder(),
30+
decoder: FirebaseDataDecoder = FirebaseDataDecoder())
3631
-> Callable<Request, Response> {
3732
return Callable(callable: httpsCallable(name), encoder: encoder, decoder: decoder)
3833
}
39-
40-
/// Creates a reference to the Callable HTTPS trigger with the given name. The types of the `Encodable`
41-
/// request and tyhe `Decodable` response will be inferred by the compiler.
42-
///
43-
/// At the call site, use the following syntax:
44-
///
45-
/// let greeter: Callable<DataTestRequest, DataTestResponse> = functions.httpsCallable("greeter")
46-
/// try greeter(data) { result in
47-
/// print(result.greeting)
48-
/// }
49-
///
50-
/// - Parameters:
51-
/// - name: The name of the Callable HTTPS trigger
52-
func httpsCallable<Request, Response>(_ name: String,
53-
encoder: StructureEncoder = StructureEncoder(),
54-
decoder: StructureDecoder = StructureDecoder())
55-
-> Callable<Request, Response> where Request: Encodable, Response: Decodable {
56-
return Callable(callable: httpsCallable(name), encoder: encoder, decoder: decoder)
57-
}
5834
}
5935

60-
/**
61-
* A `Callable` is reference to a particular Callable HTTPS trigger in Cloud Functions.
62-
*/
36+
// A `Callable` is reference to a particular Callable HTTPS trigger in Cloud Functions.
6337
public struct Callable<Request: Encodable, Response: Decodable> {
64-
/**
65-
* The timeout to use when calling the function. Defaults to 60 seconds.
66-
*/
38+
/// The timeout to use when calling the function. Defaults to 60 seconds.
6739
public var timeoutInterval: TimeInterval {
6840
get {
6941
callable.timeoutInterval
@@ -78,116 +50,127 @@ public struct Callable<Request: Encodable, Response: Decodable> {
7850
}
7951

8052
private let callable: HTTPSCallable
81-
private let encoder: StructureEncoder
82-
private let decoder: StructureDecoder
53+
private let encoder: FirebaseDataEncoder
54+
private let decoder: FirebaseDataDecoder
8355

84-
init(callable: HTTPSCallable, encoder: StructureEncoder, decoder: StructureDecoder) {
56+
init(callable: HTTPSCallable, encoder: FirebaseDataEncoder, decoder: FirebaseDataDecoder) {
8557
self.callable = callable
8658
self.encoder = encoder
8759
self.decoder = decoder
8860
}
8961

90-
/**
91-
* Executes this Callable HTTPS trigger asynchronously.
92-
*
93-
* The data passed into the trigger must be of the generic `Request` type:
94-
*
95-
* The request to the Cloud Functions backend made by this method automatically includes a
96-
* Firebase Instance ID token to identify the app instance. If a user is logged in with Firebase
97-
* Auth, an auth ID token for the user is also automatically included.
98-
*
99-
* Firebase Instance ID sends data to the Firebase backend periodically to collect information
100-
* regarding the app instance. To stop this, see `[FIRInstanceID deleteIDWithHandler:]`. It
101-
* resumes with a new Instance ID the next time you call this method.
102-
*
103-
* - Parameter data: Parameters to pass to the trigger.
104-
* - Parameter completion: The block to call when the HTTPS request has completed.
105-
*
106-
* - Throws: An error if any value throws an error during encoding.
107-
*/
62+
/// Executes this Callable HTTPS trigger asynchronously.
63+
///
64+
/// The data passed into the trigger must be of the generic `Request` type:
65+
///
66+
/// The request to the Cloud Functions backend made by this method automatically includes a
67+
/// FCM token to identify the app instance. If a user is logged in with Firebase
68+
/// Auth, an auth ID token for the user is also automatically included.
69+
///
70+
/// Firebase Cloud Messaging sends data to the Firebase backend periodically to collect information
71+
/// regarding the app instance. To stop this, see `Messaging.deleteData()`. It
72+
/// resumes with a new FCM Token the next time you call this method.
73+
///
74+
/// - Parameter data: Parameters to pass to the trigger.
75+
/// - Parameter completion: The block to call when the HTTPS request has completed.
10876
public func call(_ data: Request,
10977
completion: @escaping (Result<Response, Error>)
110-
-> Void) throws {
111-
let encoded = try encoder.encode(data)
78+
-> Void) {
79+
do {
80+
let encoded = try encoder.encode(data)
11281

113-
callable.call(encoded) { result, error in
114-
do {
115-
if let result = result {
116-
let decoded = try decoder.decode(Response.self, from: result.data)
117-
completion(.success(decoded))
118-
} else if let error = error {
82+
callable.call(encoded) { result, error in
83+
do {
84+
if let result = result {
85+
let decoded = try decoder.decode(Response.self, from: result.data)
86+
completion(.success(decoded))
87+
} else if let error = error {
88+
completion(.failure(error))
89+
} else {
90+
completion(.failure(CallableError.internalError))
91+
}
92+
} catch {
11993
completion(.failure(error))
120-
} else {
121-
completion(.failure(CallableError.internalError))
12294
}
123-
} catch {
124-
completion(.failure(error))
12595
}
96+
} catch {
97+
completion(.failure(error))
12698
}
12799
}
128100

129101
/// Creates a directly callable function.
130102
///
131-
/// This allows users to call a HTTPS Callable Funciton like a normal Swift function:
132-
///
103+
/// This allows users to call a HTTPS Callable Function like a normal Swift function:
104+
/// ```swift
133105
/// let greeter = functions.httpsCallable("greeter",
134106
/// requestType: GreetingRequest.self,
135107
/// responseType: GreetingResponse.self)
136-
/// try greeter(data) { result in
108+
/// greeter(data) { result in
137109
/// print(result.greeting)
138110
/// }
139-
///
111+
/// ```
112+
/// You can also call a HTTPS Callable function using the following syntax:
113+
/// ```swift
114+
/// let greeter: Callable<GreetingRequest, GreetingResponse> = functions.httpsCallable("greeter")
115+
/// greeter(data) { result in
116+
/// print(result.greeting)
117+
/// }
118+
/// ```
140119
/// - Parameters:
141120
/// - data: Parameters to pass to the trigger.
142121
/// - completion: The block to call when the HTTPS request has completed.
143122
public func callAsFunction(_ data: Request,
144123
completion: @escaping (Result<Response, Error>)
145-
-> Void) throws {
146-
try call(data, completion: completion)
124+
-> Void) {
125+
call(data, completion: completion)
147126
}
148127

149128
#if compiler(>=5.5) && canImport(_Concurrency)
150-
/**
151-
* Executes this Callable HTTPS trigger asynchronously.
152-
*
153-
* The data passed into the trigger must be of the generic `Request` type:
154-
*
155-
* The request to the Cloud Functions backend made by this method automatically includes a
156-
* Firebase Instance ID token to identify the app instance. If a user is logged in with Firebase
157-
* Auth, an auth ID token for the user is also automatically included.
158-
*
159-
* Firebase Instance ID sends data to the Firebase backend periodically to collect information
160-
* regarding the app instance. To stop this, see `[FIRInstanceID deleteIDWithHandler:]`. It
161-
* resumes with a new Instance ID the next time you call this method.
162-
*
163-
* - Parameter data: The `Request` representing the data to pass to the trigger.
164-
*
165-
* - Throws: An error if any value throws an error during encoding.
166-
* - Throws: An error if any value throws an error during decoding.
167-
* - Throws: An error if the callable fails to complete
168-
*
169-
* - Returns: The decoded `Response` value
170-
*/
129+
/// Executes this Callable HTTPS trigger asynchronously.
130+
///
131+
/// The data passed into the trigger must be of the generic `Request` type:
132+
///
133+
/// The request to the Cloud Functions backend made by this method automatically includes a
134+
/// FCM token to identify the app instance. If a user is logged in with Firebase
135+
/// Auth, an auth ID token for the user is also automatically included.
136+
///
137+
/// Firebase Cloud Messaging sends data to the Firebase backend periodically to collect information
138+
/// regarding the app instance. To stop this, see `Messaging.deleteData()`. It
139+
/// resumes with a new FCM Token the next time you call this method.
140+
///
141+
/// - Parameter data: The `Request` representing the data to pass to the trigger.
142+
///
143+
/// - Throws: An error if any value throws an error during encoding.
144+
/// - Throws: An error if any value throws an error during decoding.
145+
/// - Throws: An error if the callable fails to complete
146+
///
147+
/// - Returns: The decoded `Response` value
171148
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
172149
public func call(_ data: Request,
173-
encoder: StructureEncoder = StructureEncoder(),
174-
decoder: StructureDecoder =
175-
StructureDecoder()) async throws -> Response {
150+
encoder: FirebaseDataEncoder = FirebaseDataEncoder(),
151+
decoder: FirebaseDataDecoder =
152+
FirebaseDataDecoder()) async throws -> Response {
176153
let encoded = try encoder.encode(data)
177154
let result = try await callable.call(encoded)
178155
return try decoder.decode(Response.self, from: result.data)
179156
}
180157

181158
/// Creates a directly callable function.
182159
///
183-
/// This allows users to call a HTTPS Callable Funciton like a normal Swift function:
184-
///
160+
/// This allows users to call a HTTPS Callable Function like a normal Swift function:
161+
/// ```swift
185162
/// let greeter = functions.httpsCallable("greeter",
186163
/// requestType: GreetingRequest.self,
187164
/// responseType: GreetingResponse.self)
188165
/// let result = try await greeter(data)
189166
/// print(result.greeting)
190-
///
167+
/// ```
168+
/// You can also call a HTTPS Callable function using the following syntax:
169+
/// ```swift
170+
/// let greeter: Callable<GreetingRequest, GreetingResponse> = functions.httpsCallable("greeter")
171+
/// let result = try await greeter(data)
172+
/// print(result.greeting)
173+
/// ```
191174
/// - Parameters:
192175
/// - data: Parameters to pass to the trigger.
193176
/// - Returns: The decoded `Response` value

0 commit comments

Comments
 (0)