Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
60 changed files
with
7,332 additions
and
20 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Copyright 2020 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
name: combine | ||
|
||
on: | ||
pull_request: | ||
paths: | ||
# Combine sources | ||
- 'FirebaseCombineSwift/**' | ||
|
||
# Podspec | ||
- 'FirebaseCombineSwift.podspec' | ||
|
||
# This workflow | ||
- '.github/workflows/combine.yml' | ||
|
||
# Rebuild on Ruby infrastructure changes. | ||
- 'Gemfile' | ||
|
||
schedule: | ||
# Run every day at 11pm (PST) - cron uses UTC times | ||
- cron: '0 7 * * *' | ||
|
||
jobs: | ||
xcodebuild: | ||
# Don't run on private repo unless it is a PR. | ||
if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'pull_request' | ||
runs-on: macos-latest | ||
|
||
strategy: | ||
matrix: | ||
target: [iOS] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Setup build | ||
run: scripts/install_prereqs.sh CombineSwift ${{ matrix.target }} xcodebuild | ||
|
||
- name: Build and test | ||
run: scripts/third_party/travis/retry.sh scripts/build.sh CombineSwift ${{ matrix.target }} xcodebuild |
52 changes: 52 additions & 0 deletions
52
.swiftpm/xcode/xcshareddata/xcschemes/FirestoreTestingSupportTests.xcscheme
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<Scheme | ||
LastUpgradeVersion = "1240" | ||
version = "1.3"> | ||
<BuildAction | ||
parallelizeBuildables = "YES" | ||
buildImplicitDependencies = "YES"> | ||
</BuildAction> | ||
<TestAction | ||
buildConfiguration = "Debug" | ||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
shouldUseLaunchSchemeArgsEnv = "YES"> | ||
<Testables> | ||
<TestableReference | ||
skipped = "NO"> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "FirestoreTestingSupportTests" | ||
BuildableName = "FirestoreTestingSupportTests" | ||
BlueprintName = "FirestoreTestingSupportTests" | ||
ReferencedContainer = "container:"> | ||
</BuildableReference> | ||
</TestableReference> | ||
</Testables> | ||
</TestAction> | ||
<LaunchAction | ||
buildConfiguration = "Debug" | ||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
launchStyle = "0" | ||
useCustomWorkingDirectory = "NO" | ||
ignoresPersistentStateOnLaunch = "NO" | ||
debugDocumentVersioning = "YES" | ||
debugServiceExtension = "internal" | ||
allowLocationSimulation = "YES"> | ||
</LaunchAction> | ||
<ProfileAction | ||
buildConfiguration = "Release" | ||
shouldUseLaunchSchemeArgsEnv = "YES" | ||
savedToolIdentifier = "" | ||
useCustomWorkingDirectory = "NO" | ||
debugDocumentVersioning = "YES"> | ||
</ProfileAction> | ||
<AnalyzeAction | ||
buildConfiguration = "Debug"> | ||
</AnalyzeAction> | ||
<ArchiveAction | ||
buildConfiguration = "Release" | ||
revealArchiveInOrganizer = "YES"> | ||
</ArchiveAction> | ||
</Scheme> |
28 changes: 13 additions & 15 deletions
28
FirebaseAuth/Tests/Sample/SwiftApiTests/Credentials.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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
Pod::Spec.new do |s| | ||
s.name = 'FirebaseAuthTestingSupport' | ||
s.version = '1.0.0' | ||
s.summary = 'Firebase SDKs testing support types and utilities.' | ||
|
||
s.description = <<-DESC | ||
Type declarations and utilities needed for unit testing of the code dependent on Firebase SDKs | ||
DESC | ||
|
||
s.homepage = 'https://developers.google.com/' | ||
s.license = { :type => 'Apache', :file => 'LICENSE' } | ||
s.authors = 'Google, Inc.' | ||
|
||
s.source = { | ||
:git => 'https://github.com/Firebase/firebase-ios-sdk.git', | ||
:tag => 'CocoaPods-' + s.version.to_s | ||
} | ||
|
||
ios_deployment_target = '10.0' | ||
osx_deployment_target = '10.12' | ||
tvos_deployment_target = '10.0' | ||
watchos_deployment_target = '6.0' | ||
|
||
s.ios.deployment_target = ios_deployment_target | ||
s.osx.deployment_target = osx_deployment_target | ||
s.tvos.deployment_target = tvos_deployment_target | ||
s.watchos.deployment_target = watchos_deployment_target | ||
|
||
s.cocoapods_version = '>= 1.4.0' | ||
s.prefix_header_file = false | ||
s.requires_arc = true | ||
|
||
base_dir = 'FirebaseTestingSupport/Auth/' | ||
|
||
s.source_files = [ | ||
base_dir + 'Sources/**/*.{m,mm,h}', | ||
] | ||
|
||
s.public_header_files = base_dir + '**/*.h' | ||
|
||
s.dependency 'FirebaseAuth', '~> 7.7' | ||
|
||
s.pod_target_xcconfig = { | ||
'GCC_C_LANGUAGE_STANDARD' => 'c99', | ||
'OTHER_CFLAGS' => '-fno-autolink', | ||
'HEADER_SEARCH_PATHS' => | ||
'"${PODS_TARGET_SRCROOT}" ' | ||
} | ||
|
||
s.test_spec 'unit' do |unit_tests| | ||
unit_tests.scheme = { :code_coverage => true } | ||
unit_tests.platforms = {:ios => ios_deployment_target, :osx => osx_deployment_target, :tvos => tvos_deployment_target} | ||
unit_tests.source_files = [ | ||
base_dir + 'Tests/**/*.swift' | ||
] | ||
end | ||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
Pod::Spec.new do |s| | ||
s.name = 'FirebaseCombineSwift' | ||
s.version = '7.6.0' | ||
s.summary = 'Swift extensions with Combine support for Firebase' | ||
|
||
s.description = <<-DESC | ||
Combine Publishers for Firebase. | ||
DESC | ||
|
||
s.homepage = 'https://firebase.google.com' | ||
s.license = { :type => 'Apache', :file => 'LICENSE' } | ||
s.authors = 'Google, Inc.' | ||
|
||
s.source = { | ||
:git => 'https://github.com/firebase/firebase-ios-sdk.git', | ||
:tag => 'CocoaPods-' + s.version.to_s | ||
} | ||
|
||
s.social_media_url = 'https://twitter.com/Firebase' | ||
|
||
s.swift_version = '5.0' | ||
|
||
ios_deployment_target = '13.0' | ||
osx_deployment_target = '10.15' | ||
tvos_deployment_target = '13.0' | ||
watchos_deployment_target = '6.0' | ||
|
||
s.ios.deployment_target = ios_deployment_target | ||
s.osx.deployment_target = osx_deployment_target | ||
s.tvos.deployment_target = tvos_deployment_target | ||
s.watchos.deployment_target = watchos_deployment_target | ||
|
||
s.cocoapods_version = '>= 1.4.0' | ||
s.prefix_header_file = false | ||
|
||
source = 'FirebaseCombineSwift/Sources/' | ||
s.exclude_files = [ | ||
source + 'Core/**/*.swift', | ||
] | ||
s.source_files = [ | ||
source + '**/*.swift', | ||
source + '**/*.m', | ||
] | ||
s.public_header_files = [ | ||
source + '**/*.h', | ||
] | ||
|
||
s.framework = 'Foundation' | ||
s.ios.framework = 'UIKit' | ||
s.osx.framework = 'AppKit' | ||
s.tvos.framework = 'UIKit' | ||
|
||
s.dependency 'FirebaseCore', '~> 7.6' | ||
s.dependency 'FirebaseAuth', '~> 7.6' | ||
s.dependency 'FirebaseFunctions', '~> 7.6' | ||
s.dependency 'FirebaseStorage', '~> 7.6' | ||
s.dependency 'FirebaseStorageSwift', '~> 7.6-beta' | ||
|
||
s.pod_target_xcconfig = { | ||
'HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}"', | ||
} | ||
|
||
s.test_spec 'unit' do |unit_tests| | ||
unit_tests.scheme = { :code_coverage => true } | ||
unit_tests.platforms = { | ||
:ios => ios_deployment_target, | ||
:osx => osx_deployment_target, | ||
:tvos => tvos_deployment_target | ||
} | ||
unit_tests.source_files = [ | ||
'FirebaseCombineSwift/Tests/Unit/**/*.swift', | ||
'FirebaseCombineSwift/Tests/Unit/**/*.h', | ||
'SharedTestUtilities/FIROptionsMock.[mh]', | ||
'SharedTestUtilities/FIRComponentTestUtilities.[mh]', | ||
] | ||
unit_tests.exclude_files = 'FirebaseCombineSwift/Tests/Unit/**/*Template.swift' | ||
unit_tests.requires_app_host = true | ||
unit_tests.pod_target_xcconfig = { | ||
'SWIFT_OBJC_BRIDGING_HEADER' => '$(PODS_TARGET_SRCROOT)/FirebaseCombineSwift/Tests/Unit/FirebaseCombine-unit-Bridging-Header.h' | ||
} | ||
unit_tests.dependency 'OCMock' | ||
unit_tests.dependency 'FirebaseAuthTestingSupport' | ||
unit_tests.dependency 'FirebaseFunctionsTestingSupport' | ||
end | ||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Unreleased | ||
|
||
- [feature] Added Combine support for Cloud Functions for Firebase | ||
- [feature] WIP: Added Combine support for Firebase Auth | ||
- [feature] WIP: Added Combine support for Firebase Storage |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Decisions | ||
|
||
This file documents some of the decisions we made when developing Combine support for Firebase. | ||
|
||
# Module structure | ||
|
||
## Discussion | ||
The general idea is to keep all Combine-related code in a separate module (`FirebaseCombineSwift`, to match the naming scheme used for `FirebaseFirestoreSwift` and `FirebaseStorageSwift`). | ||
|
||
By using the `#if canImport(moduleName)` directive, we can make sure to only enable the publishers for a module that developers have imported into a build target. | ||
|
||
|
||
# Implementing Publishers | ||
|
||
## Custom Publishers vs. wrapping in Futures / using PassthroughSubject | ||
|
||
Instead of implementing [custom publishers](https://thoughtbot.com/blog/lets-build-a-custom-publisher-in-combine), which [Apple discourages developers from doing](https://developer.apple.com/documentation/combine/publisher), we make use of [`PassthroughSubject`](https://developer.apple.com/documentation/combine/passthroughsubject) (for publishers that emit a stream of events), and [`Future`](https://developer.apple.com/documentation/combine/future) for one-shot calls that produce a single value. | ||
|
||
## Using capture lists | ||
|
||
After discussing internally, we came to the conclusion that the outer closure in the following piece of code is non-escaping, hence there is no benefit to weakly capture `self`. As the inner closure does't refer to `self`, the reference does not outlive the current call stack. | ||
|
||
It is thus safe to not use `[weak self]` in this instance. | ||
|
||
```swift | ||
extension Auth { | ||
public func createUser(withEmail email: String, | ||
password: String) -> Future<AuthDataResult, Error> { | ||
Future<AuthDataResult, Error> { /* [weak self] <-- not required */ promise in | ||
self?.createUser(withEmail: email, password: password) { authDataResult, error in | ||
if let error = error { | ||
promise(.failure(error)) | ||
} else if let authDataResult = authDataResult { | ||
promise(.success(authDataResult)) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
|
||
# Method naming | ||
|
||
## Discussion | ||
* Methods that might send a **stream of events** over time will receive a `Publisher` suffix, in line with Apple's own APIs. Any `add` prefix will be removed. This helps to clarify that the user is not _adding_ something that they will have to remove later on ([as is required](https://firebase.google.com/docs/auth/ios/start#listen_for_authentication_state) in most of Firebase's existing APIs). Instead, the result of the publisher needs to be handled just like any other publisher (i.e. be kept in a set of `Cancellable`s). | ||
|
||
Examples: | ||
* `addStateDidChangeListener` -> `authStateDidChangePublisher` | ||
* `addSnapshotListener` -> `snapshotPublisher` | ||
|
||
* Methods that **return a result once** will not receive a suffix. This effectively means that these methods are overloads to their existing counterparts that take a closure. To silence any `Result of call to xzy is unused` warnings, these methods need to be prefixed with `@discardableresult`. This shouldn't be a problem, since the Future that is created inside those functions is called immediately and will be disposed of by the runtime upon returning from the inner closure. | ||
|
||
Examples: | ||
* `signIn` -> `signIn` | ||
* `createUser` -> `createUser` | ||
|
||
## Options considered | ||
Using the same method and parameter names for one-shot asynchronous methods results in both methods to be shown in close proximity when invoking code completion | ||
|
||
![image](https://user-images.githubusercontent.com/232107/99672274-76f05680-2a73-11eb-880a-3563f293de7d.png) | ||
|
||
To achieve the same for methods that return a stream of events, we'd have to name those `addXzyListener`. This would be in contrast to Apple's naming scheme (e.g. `dataTask(with:completionHandler)` -> `dataTaskPublisher(for:)` |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Developing | ||
|
||
This is a quick overview to help you get started contributing to Firebase Combine. | ||
|
||
## Prerequisites | ||
|
||
* Xcode 12.x (or later) | ||
* CocoaPods 1.10.x (or later) | ||
* [CocoaPods Generate](https://github.com/square/cocoapods-generate) | ||
|
||
## Setting up your development environment | ||
|
||
* Check out firebase-ios-sdk | ||
* Install utilities | ||
|
||
```bash | ||
$ ./scripts/setup_check.sh | ||
$ ./scripts/setup_bundler.sh | ||
``` | ||
|
||
## Generating the development project | ||
|
||
For developing _Firebase Combine_, you'll need a development project that imports the relevant pods. | ||
|
||
Run the following command to generate and open the development project: | ||
|
||
```bash | ||
$ pod gen FirebaseCombineSwift.podspec --local-sources=./ --auto-open --platforms=ios | ||
``` | ||
|
||
## Checking in code | ||
|
||
Before checking in your code, make sure to check your code against the coding styleguide by running the following command: | ||
|
||
```bash | ||
$ ./scripts/check.sh --allow-dirty | ||
``` |
Oops, something went wrong.