Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/spm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,4 @@ jobs:
- name: Integration Test Setup
run: Tests/Integration/Emulator/start-emulator.sh
- name: Unit and Integration Tests
run: scripts/third_party/travis/retry.sh ./scripts/build.sh FirebaseDataConnect ${{ matrix.target }} spm
run: scripts/third_party/travis/retry.sh ./scripts/build.sh FirebaseDataConnect-Package ${{ matrix.target }} spm
12 changes: 12 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ let package = Package(
name: "FirebaseDataConnect",
targets: ["FirebaseDataConnect"]
),
.executable(name: "Start FDC Tools", targets: ["SetupDevEnv"]),
],
dependencies: [
firebaseDependency(),
Expand All @@ -53,6 +54,12 @@ let package = Package(
],
path: "Sources"
),
.target(name: "ShellExecutor", dependencies: [], path: "Tools/ShellExecutor"),
.executableTarget(
name: "SetupDevEnv",
dependencies: ["ShellExecutor"],
path: "Tools/SetupDevEnv"
),
.testTarget(
name: "FirebaseDataConnectUnit",
dependencies: ["FirebaseDataConnect"],
Expand All @@ -67,6 +74,11 @@ let package = Package(
.copy("Resources/fdc-kitchensink"),
]
),
.testTarget(
name: "ShellExecutorTests",
dependencies: ["ShellExecutor"],
path: "Tests/ShellExecutor"
),
]
)

Expand Down
52 changes: 44 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,61 @@
# Firebase Data Connect iOS Open Source Development

This repository contains the source code of Firebase Data Connect SDKs for development on iOS and other Apple platforms.
This repository contains the source code of Firebase Data Connect Swift SDKs for development on iOS and other Apple platforms.

Firebase Data Connect (https://firebase.google.com/products/data-connect) lets you build applications with CloudSQL for PostgreSQL
Firebase Data Connect (https://firebase.google.com/docs/data-connect) lets you build applications with CloudSQL for PostgreSQL.

Firebase is an app development platform with tools to help you build, grow, and
monetize your app. More information about Firebase can be found on the
[official Firebase website](https://firebase.google.com).

## Getting Started
## Installation

Learn how to develop on Data Connect - [Quick Start](https://firebase.google.com/docs/data-connect/quickstart).
This process shows you how to setup Firebase Data Connect tools with Xcode.

Try out a comprehensive sample app - [FriendlyFlix](https://github.com/firebase/data-connect-ios-sdk/tree/main/Examples/FriendlyFlix)
* Get the Firebase Data Connect iOS SDK.
```
git clone https://github.com/firebase/data-connect-ios-sdk.git
```
* Add it as a local package dependency in your Xcode project
* From your Xcode project, select `File -> Add Package Dependencies -> Add Local`.
* Select the `data-connect-ios-sdk` folder containing the cloned SDK.
* Add `FirebaseDataConnect` to your app target.
* Add and Edit Xcode Scheme
* From your list of schemes, select `New Scheme`.
* Xcode should show you `Start FDC Tools` as a potential scheme. Select that.
* Adjust working directory
* Edit the `Start FDC Tools` Scheme from `Edit Scheme... -> Start FDC Tools`.
* Go to `Run -> Options -> Working Directory`
* Select `Custom working directory` and pick your Xcode project folder
* This ensures that Firebase Data Connect tools start in the correct folder each time.
* Run the `Start FDC Tools` target selecting `My Mac` as the device.
* This should start the tools in a separate browser window (or tab).
* Now that you have the tools, try out our [Codelab](https://firebase.google.com/codelabs/firebase-dataconnect-ios#0)
* Learn more about designing schemas, queries and mutations - [Design Schemas](https://firebase.google.com/docs/data-connect/schemas-guide)
## Installation
* Generated SDKs are Swift packages. Add the generated SDKs to your project as a Local Package dependency and start using them in your app.
* Generated APIs support `@Observable` (Observation framework) for easy integration into SwiftUI apps.
* UIKit apps can make use of the underlying `Combine` publishers.
* All Query and Mutation APIs are `async` calls and can participate in Swift concurrency.
* Since you cloned the `data-connect-ios-sdk`, be sure to reference your local folder to generate SDKs.
* In the `connector.yaml`, configure the Swift SDK generation to point to the local path where you cloned the Data Connect iOS SDK using the `coreSdkPackageLocation` parameter. Example -
```yaml
generate:
swiftSdk:
outputDir: ../../dataconnect-generated/swift
package: DefaultConnector #change this to your project specific name
coreSdkPackageLocation: /Users/abc/Code/data-connect-ios-sdk
```
The Data Connect SDK should get automatically added as a dependency if you use generated SDKs. However, if you need to add it manually, use the following instructions for Swift Package Manager.
There are other paths to get setup with Firebase Data Connect tools such as from the Firebase Console. To learn more visit - [Quick Start](https://firebase.google.com/docs/data-connect/quickstart).
### Swift Package Manager
## Sample App and Code Lab
* [Codelab](https://firebase.google.com/codelabs/firebase-dataconnect-ios#0)
* Comprehensive Sample app - [FriendlyFlix](https://github.com/firebase/data-connect-ios-sdk/tree/main/Examples/FriendlyFlix)
### Swift Package Manager
Instructions for [Swift Package Manager](https://swift.org/package-manager/) support can be
found in the [SwiftPackageManager.md](SwiftPackageManager.md) Markdown file.
Expand Down
89 changes: 89 additions & 0 deletions Tests/ShellExecutor/TestExecutor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2025 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.

import XCTest

#if os(macOS)
@testable import ShellExecutor

@available(macOS 12.0, *)
final class ShellExecutorTests: XCTestCase {
var executor: ShellExecutor!

override func setUp() {
super.setUp()
// This is run before each test
executor = ShellExecutor()
}

/// Tests that a simple, successful command completes without throwing a Swift error.
func testSuccessfulCommand() {
// The `true` command does nothing and exits with status 0.
XCTAssertNoThrow(
try executor.run("true"),
"A successful command should not throw an error."
)
}

/// Tests that a failing command completes without throwing a Swift error,
/// as our function handles the non-zero exit code internally.
func testFailingCommand() {
// The `false` command does nothing and exits with status 1.
XCTAssertNoThrow(
try executor.run("false"),
"A failing command should be handled gracefully, not throw."
)
}

/// Tests if the standard output from the command is correctly captured and printed.
func testStandardOutputCapture() throws {
let testString = "Hello from XCTest!"
let command = "echo '\(testString)'"

// We need to capture the process's stdout to verify it.
// This is a common pattern for testing command-line output.
let outputPipe = Pipe()

// Save the original standard output file handle
let originalStdout = dup(STDOUT_FILENO)

// Redirect stdout to our pipe's write end
dup2(outputPipe.fileHandleForWriting.fileDescriptor, STDOUT_FILENO)

// Run the command. Its output will go into the pipe.
try executor.run(command)

// Close the write end of the pipe to signal end-of-file
try outputPipe.fileHandleForWriting.close()

// Restore the original standard output
dup2(originalStdout, STDOUT_FILENO)
close(originalStdout)

// Read all data from the pipe
let capturedData = outputPipe.fileHandleForReading.readDataToEndOfFile()
let capturedOutput = String(data: capturedData, encoding: .utf8) ?? ""

XCTAssertTrue(
capturedOutput.contains(testString),
"The captured output should contain the test string '\(testString)'"
)

XCTAssertTrue(
capturedOutput.contains("✅ ShellExecutor: Command finished successfully."),
"The output should contain the success message."
)
}
}
#endif
49 changes: 49 additions & 0 deletions Tools/SetupDevEnv/SetupDevEnv.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2025 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.

import Foundation

import ShellExecutor

// port on which FDC tools (code-server) listen
let FDC_TOOLS_PORT: UInt = 9394

@available(macOS 12.0, *)
@main
struct SetupDevEnv {
static func main() {
#if os(macOS)
let currentDirectoryPath = FileManager.default.currentDirectoryPath
print("Attempting to start Data Connect Tools in Directory: \(currentDirectoryPath)")

let executor = ShellExecutor()

do {
// When the `Start FDC Tools` process is stopped from Xcode,
// it still leaves an orphaned code-server process since SIGKILL isn't received by the
// command line utility
try executor.killProcessOnPort(FDC_TOOLS_PORT)
} catch {
print("❌ Error killing process \(error)")
}

do {
let commandToRun = "curl -sL https://firebase.tools/dataconnect | bash"
try executor.run(commandToRun)
} catch {
print("❌ Error running command: \(error)")
}
#endif // if macos
}
}
Loading
Loading