diff --git a/Changelog.md b/Changelog.md index 139597f..2c263ce 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,2 +1,3 @@ - +# 11.3.0-beta +[added] Initial public beta release of the SDK. For more information visit [Firebase Data Connect](https://firebase.google.com/products/data-connect) diff --git a/README.md b/README.md index 270cef6..70983f5 100644 --- a/README.md +++ b/README.md @@ -16,160 +16,8 @@ Instructions for [Swift Package Manager](https://swift.org/package-manager/) sup found in the [SwiftPackageManager.md](SwiftPackageManager.md) Markdown file. ## Getting Started -Firebase Data Connect is in Private Preview at no cost for a limited time. Sign up the program at https://firebase.google.com/products/data-connect. -Once you are selected as an allowlist member, you should be able to create a Cloud SQL instance through Firebase Data Connect console. - -Here's a quick rundown of steps to get you started. Learn more about details at the official [Getting Started documentation](https://firebase.google.com/docs/data-connect/quickstart). - -### 1. Create a new Data Connect service and Cloud SQL instance. -* Go to Firebase Console and select Firebase Data Connect from the Left Navigation bar to create a new Data Connect service and a Cloud SQL instance. You have to be in Blaze plan and you can view the details of pricing at https://firebase.google.com/pricing. -* Select us-central1 region if you want to try out vector search with Data Connect later. -* Your Cloud SQL instance is now to be provisioned, you can view and manage the instance at the Google Cloud console. - -### 2. Setup your iOS app and [initialize Firebase](https://firebase.google.com/docs/ios/setup) - -#### The following steps will guide you to setup your schema and create query operation that you need for your app. The toolings below will help you to test out your query with dummy data and once you are happy with your query, the tools will help generate client code for that query so you can call directly from your app. - - -### 3. Set up [Firebase CLI](https://firebase.google.com/docs/cli) - -* If you already have CLI, make sure you always update to the latest version -``` -npm install -g firebase-tools -``` - -### 4. Set up VSCode -You will need VS Code and its Firebase extension (VS Code extension) to automatically generate Swift code for your queries. -* Install VS Code -* Download the [extension](https://firebasestorage.googleapis.com/v0/b/firemat-preview-drop/o/vsix%2Ffirebase-vscode-latest.vsix?alt=media) and drag it into the "Extensions" in the Left Navigation bar for installation. Keep in mind double clicking the file won't install. -* Create a fdc folder where you like to have firebase data connect configuration. -``` -mkdir fdc -``` -* Open VS Code from folder you just created -* Select the Firebase icon on the left and login -* Click on "Run firebase init" button - -* Select the first option of Data Connect -* Enter/Select the project, service and database ID you setup on the console -* Enter to select the default connector ID and complete the rest of the process - -### 5. Set up generated SDK location -In the connector.yaml file, add the following code to enable swift code to be generated. - -``` - swiftSdk: - outputDir: "../swift-generated/" - package: "User" -``` -* You should see swift code is generated inside the ../swift-generated/User/ folder - -### 6. Create a schema and generate some dummy data -* In the schema.gql file, uncomment the schema -``` -type User @table(key: "uid") { - uid: String! - name: String! - address: String! -} -``` -* On top of the schema User, an "Add data" button start showing up, click on it to generate a User_insert.gql file -* Fill out the fields and click on Run button to run the query to add a user dummy data for testing - -### 7. Deploy your schema -* To deploy your schema, you will need your Cloud SQL instance to be ready. You can view the instance at the Cloud Cloud console. -* Select the Firebase icon on the left and Click on the "Deploy all" button to deploy all the schema and operations to backend. -* You can now see your schemas on the Firebase Console. - -### 8. Set up a mutation -In the mutations.gql file, uncomment the "CreateUser" query. -* In the CONFIGURATION -> VARIABLES, enter -``` -{ - "name" : "dummy_name", - "address" : "dummy_address" -} -``` -* In the CONFIGURATION -> AUTHENTICATION, select Run as "Authenticated". -* Click on the "Run" button above the query. -* You should see your dummy data is added. -* Select the Firebase icon on the left and Click on the "Deploy all" button to deploy all the schema and operations to backend. -* As you see this operation needs authentication, so you will need to be authenticated with Firebase Authentication in your client app when you call this operation in iOS app. - -#### At this point, you have the code generated for the queries you need for your app. Now let's see how you can use the generated query code in your iOS app: - -### 9. Adding the generated package to your app project -* Go to File -> Add Package Dependencies -> Add Local -* Navigate to the generated folder and select the "swift-generated/User" folder (You should see a Package.swift file in it). - -### 10. Calling the generated code from your app -``` -import FirebaseDataConnect -import Users //change this to the name of your generated package - -func executeFDCCreateUserQuery() { - Task { - do { - let result = try await DataConnect.defaultConnectorClient.createUserMutationRef(name: "dummyUserName", address: "dummyUserAddress").execute() - } catch { - } - } - } - -``` - - - - -## Development - -To develop Firebase software in this repository, ensure that you have at least -the following software: - -* Xcode 15.2 (or later) - -### Swift Package Manager -* To enable test schemes: `./scripts/setup_spm_tests.sh` -* `open Package.swift` or double click `Package.swift` in Finder. -* Xcode will open the project - * Choose a scheme for a library to build or test suite to run - * Choose a target platform by selecting the run destination along with the scheme - -### Code Formatting - -To ensure that the code is formatted consistently, run the script -[./scripts/check.sh](https://github.com/firebase/firebase-ios-sdk/blob/main/scripts/check.sh) -before creating a pull request (PR). - -GitHub Actions will verify that any code changes are done in a style-compliant -way. Install `clang-format` and `mint`: - -```console -brew install clang-format@19 -brew install mint -``` - -### Running Unit Tests - -Select a scheme and press Command-u to build a component and run its unit tests. - -### Running Sample Apps -To run the sample apps and integration tests, you'll need a valid -`GoogleService-Info.plist -` file. The Firebase Xcode project contains dummy plist -files without real values, but they can be replaced with real plist files. To get your own -`GoogleService-Info.plist` files: - -1. Go to the [Firebase Console](https://console.firebase.google.com/) -2. Create a new Firebase project, if you don't already have one -3. For each sample app you want to test, create a new Firebase app with the sample app's bundle -identifier (e.g., `com.google.Database-Example`) -4. Download the resulting `GoogleService-Info.plist` and add it to the Xcode project. - -### Coverage Report Generation - -For coverage report generation instructions, see [scripts/code_coverage_report/README](scripts/code_coverage_report/README.md) Markdown file. +Learn how to develop on Data Connect - [Quick Start](https://firebase.google.com/docs/data-connect/quickstart). ## Contributing diff --git a/Sources/DataConnect.swift b/Sources/DataConnect.swift index f883342..75f3113 100644 --- a/Sources/DataConnect.swift +++ b/Sources/DataConnect.swift @@ -38,6 +38,8 @@ public class DataConnect { // MARK: Static Creation + /// Returns an instance of DataConnect matching the parameters. + /// If a matching instance is found that is returned, otherwise a new instance is created. public class func dataConnect(app: FirebaseApp? = FirebaseApp.app(), connectorConfig: ConnectorConfig, settings: DataConnectSettings = DataConnectSettings(), @@ -108,6 +110,7 @@ public class DataConnect { // MARK: Operations + /// Returns a query ref matching the name and variables. public func query(name: String, variables: Variable, @@ -119,6 +122,7 @@ public class DataConnect { return operationsManager.queryRef(for: request, with: resultsDataType, publisher: publisher) } + /// Returns a Mutation Ref matching the name and specified variables. public func mutation(name: String, variables: Variable, diff --git a/Sources/DataConnectError.swift b/Sources/DataConnectError.swift index d23ee91..c6e299f 100644 --- a/Sources/DataConnectError.swift +++ b/Sources/DataConnectError.swift @@ -14,22 +14,24 @@ import Foundation +/// Represents an error returned by the DataConnect service @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public enum DataConnectError: Error { - // no firebase app specified. configure not complete + /// no firebase app specified. configure not complete case appNotConfigured + /// failed to configure gRPC case grpcNotConfigured - // failed to decode results from server + /// failed to decode results from server case decodeFailed - // uuid string length is not correct. + /// Invalid uuid format during encoding / decoding of data case invalidUUID - // date components specified to initialize LocalDate are invalid + /// date components specified to initialize LocalDate are invalid case invalidLocalDateFormat - // timestamp components specified to initialize Timestamp are invalid + /// timestamp components specified to initialize Timestamp are invalid case invalidTimestampFormat } diff --git a/Sources/MutationRef.swift b/Sources/MutationRef.swift index 26dce8c..7ea0cc9 100644 --- a/Sources/MutationRef.swift +++ b/Sources/MutationRef.swift @@ -25,6 +25,7 @@ struct MutationRequest: OperationRequest { } } +/// Represents a predefined graphql mutation identified by name and variables. @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public class MutationRef: OperationRef { private var request: any OperationRequest diff --git a/Sources/QueryRef.swift b/Sources/QueryRef.swift index 1a9e013..de13fcc 100644 --- a/Sources/QueryRef.swift +++ b/Sources/QueryRef.swift @@ -17,11 +17,18 @@ import Foundation import Combine import Observation +/// The type of publisher to use for the Query Ref @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public enum ResultsPublisherType { - case auto // automatically determine ObservableQueryRef - case observableObject // pre-iOS 17 ObservableObject - case observableMacro // iOS 17+ Observation framework + /// automatically determine ObservableQueryRef. + /// Tries to pick the iOS 17+ Observation but falls back to ObservableObject + case auto + + /// pre-iOS 17 ObservableObject + case observableObject + + /// iOS 17+ Observation framework + case observableMacro } @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) @@ -122,10 +129,18 @@ public protocol ObservableQueryRef: QueryRef { var lastError: DataConnectError? { get } } -// QueryRef class used with ObservableObject protocol -// data: Published variable that contains bindable results of the query. -// lastError: Published variable that contains DataConnectError if last fetch had error. -// If last fetch was successful, this variable is cleared +/// QueryRef class compatible with ObservableObject protocol +/// +/// When the requested publisher is an ObservableObject, the returned query refs will be instances +/// of this class +/// +/// This class cannot be instantiated directly. To get an instance, call the +/// ``DataConnect/dataConnect(...)`` function +/// +/// This class publishes two vars +/// - ``data``: Published variable that contains bindable results of the query. +/// - ``lastError``: Published variable that contains ``DataConnectError`` if last fetch had error. +/// If last fetch was successful, this variable is cleared @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public class QueryRefObservableObject< ResultData: Decodable, @@ -161,27 +176,43 @@ public class QueryRefObservableObject< // ObservableQueryRef implementation + /// data published by query of type `ResultData` @Published public private(set) var data: ResultData? + /// Error thrown if error occurs during execution of query. If the last fetch was successful the + /// error is cleared @Published public private(set) var lastError: DataConnectError? // QueryRef implementation + /// Executes the query and returns `ResultData`. This will also update the published `data` + /// variable public func execute() async throws -> OperationResult { let result = try await baseRef.execute() return result } + /// Returns the underlying results publisher. + /// Use this function ONLY if you plan to use the Query Ref outside of SwiftUI context - (UIKit, + /// background updates,...) public func subscribe() async throws -> AnyPublisher, Never> { return await baseRef.subscribe() } } -// QueryRef class compatible with the Observation framework introduced in iOS 17 -// data: Published variable that contains bindable results of the query. -// lastError: Published variable that contains DataConnectError if last fetch had error. -// If last fetch was successful, this variable is cleared +/// QueryRef class compatible with the Observation framework introduced in iOS 17 +/// +/// When the requested publisher is an ObservableMacri, the returned query refs will be instances +/// of this class +/// +/// This class cannot be instantiated directly. To get an instance, call the +/// ``DataConnect/dataConnect(...)`` function +/// +/// This class publishes two vars +/// - ``data``: Published variable that contains bindable results of the query. +/// - ``lastError``: Published variable that contains ``DataConnectError`` if last fetch had error. +/// If last fetch was successful, this variable is cleared @available(macOS 14, iOS 17, tvOS 17, watchOS 10, *) @Observable public class QueryRefObservation< @@ -221,17 +252,25 @@ public class QueryRefObservation< // ObservableQueryRef implementation + /// data published by query of type `ResultData` public private(set) var data: ResultData? + /// Error thrown if error occurs during execution of query. If the last fetch was successful the + /// error is cleared public private(set) var lastError: DataConnectError? // QueryRef implementation + /// Executes the query and returns `ResultData`. This will also update the published `data` + /// variable public func execute() async throws -> OperationResult { let result = try await baseRef.execute() return result } + /// Returns the underlying results publisher. + /// Use this function ONLY if you plan to use the Query Ref outside of SwiftUI context - (UIKit, + /// background updates,...) public func subscribe() async throws -> AnyPublisher, Never> { return await baseRef.subscribe() diff --git a/SwiftPackageManager.md b/SwiftPackageManager.md index 1b8785e..f361b37 100644 --- a/SwiftPackageManager.md +++ b/SwiftPackageManager.md @@ -3,18 +3,10 @@ ## Requirements - Requires Xcode 15.2 or above -- Analytics requires clients to add `-ObjC` linker option. - See [Package.swift](Package.swift) for supported platform versions. -## Limitations - -- Product availability varies by platform. See [the chart on this page](https://firebase.google.com/docs/ios/learn-more#firebase_library_support_by_platform) - for information on product availabilty for each platform. - ## Installation -> If you've previously used CocoaPods, remove them from the project with `pod deintegrate`. - ### Installing from Xcode Add a package by selecting `File` → `Add Packages…` in Xcode’s menu bar. @@ -23,9 +15,9 @@ Add a package by selecting `File` → `Add Packages…` in Xcode’s menu bar. --- -Search for the Firebase Apple SDK using the repo's URL: +Search for the Firebase Data Connect Apple SDK using the repo's URL: ```console -https://github.com/firebase/firebase-ios-sdk.git +https://github.com/firebase/data-connect-ios-sdk.git ``` Next, set the **Dependency Rule** to be `Up to Next Major Version`. @@ -36,61 +28,33 @@ Then, select **Add Package**. --- -Choose the Firebase products that you want installed in your app. - - - ---- - -If you've installed **FirebaseAnalytics**, add the `-ObjC` option to `Other Linker Flags` -in the `Build Settings` tab. +Choose the product FirebaseDataConnect to install in your app. - - ---- - -If you're using FirebaseCrashlytics, you can use -`${BUILD_DIR%/Build/*}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run` -as the run script that allows Xcode to upload your project's dSYM files. - -Another option is to use the -[upload-symbols](https://github.com/firebase/firebase-ios-sdk/raw/main/Crashlytics/upload-symbols) -script. Place it in the directory where your `.xcodeproj` file lives, -eg. `scripts/upload-symbols`, and make sure that the file is executable: -`chmod +x scripts/upload-symbols`. -This script can be used to manually upload dSYM files (for usage notes and -additional instructions, run with the `--help` parameter). - -If you're getting `error: Could not get GOOGLE_APP_ID in Google Services file from build environment` on the Crashlytics run script step and you're using Xcode 15 and specifically `User Script Sandboxing = YES`, make sure to include all input files referenced [here](https://github.com/firebase/firebase-ios-sdk/pull/11463) in the Crashlytics run script. - ---- -### Alternatively, add Firebase to a `Package.swift` manifest +### Alternatively, add Firebase Data Connect to a `Package.swift` manifest To integrate via a `Package.swift` manifest instead of Xcode, you can add -Firebase to the dependencies array of your package: +Firebase Data Connect to the dependencies array of your package: ```swift dependencies: [ .package( - name: "Firebase", - url: "https://github.com/firebase/firebase-ios-sdk.git", - .upToNextMajor(from: "10.4.0") + url: "https://github.com/firebase/data-connect-ios-sdk.git", + .upToNextMajor(from: "11.3.0") ), // Any other dependencies you have... ], ``` -Then, in any target that depends on a Firebase product, add it to the `dependencies` +Then, in any target that depends on Firebase Data Connect, add it to the `dependencies` array of that target: ```swift .target( name: "MyTargetName", dependencies: [ - // The product(s) you want (e.g. FirebaseAuth). - .product(name: "FirebaseAuth", package: "Firebase"), + .product(name: "FirebaseDataConnect", package: "data-connect-ios-sdk"), ] ), ```