From 08c6b767d94e2caae3b249fcd036706e01d701d3 Mon Sep 17 00:00:00 2001 From: Chuck Grindel Date: Mon, 6 Feb 2023 16:22:15 -0700 Subject: [PATCH] chore: add `firebase_example` with analytics example app (#198) Related to #153 --- .bazelrc | 4 +- examples/BUILD.bazel | 3 +- examples/firebase_example/.bazelrc | 4 - examples/firebase_example/BUILD.bazel | 34 - examples/firebase_example/README.md | 6 + .../AnalyticsExample.entitlements | 8 + .../AnalyticsExample/AnalyticsView.swift | 349 ++++++++ .../AnalyticsViewController.swift | 135 +++ .../AnalyticsExample/AppDelegate.swift | 39 + .../analytics/AnalyticsExample/BUILD.bazel | 38 + .../Base.lproj/LaunchScreen.storyboard | 54 ++ .../AnalyticsExample/BlogViewController.swift | 155 ++++ .../analytics/AnalyticsExample/Info.plist | 60 ++ .../AnalyticsExample/SceneDelegate.swift | 33 + examples/firebase_example/set_up_clean_test | 81 +- .../firebase_example/swift_deps_index.json | 771 +++++++++++++++--- 16 files changed, 1533 insertions(+), 241 deletions(-) create mode 100644 examples/firebase_example/README.md create mode 100644 examples/firebase_example/analytics/AnalyticsExample/AnalyticsExample.entitlements create mode 100644 examples/firebase_example/analytics/AnalyticsExample/AnalyticsView.swift create mode 100644 examples/firebase_example/analytics/AnalyticsExample/AnalyticsViewController.swift create mode 100644 examples/firebase_example/analytics/AnalyticsExample/AppDelegate.swift create mode 100644 examples/firebase_example/analytics/AnalyticsExample/BUILD.bazel create mode 100644 examples/firebase_example/analytics/AnalyticsExample/Base.lproj/LaunchScreen.storyboard create mode 100644 examples/firebase_example/analytics/AnalyticsExample/BlogViewController.swift create mode 100644 examples/firebase_example/analytics/AnalyticsExample/Info.plist create mode 100644 examples/firebase_example/analytics/AnalyticsExample/SceneDelegate.swift diff --git a/.bazelrc b/.bazelrc index c0e1e1665..e09f2b7e2 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,7 +1,7 @@ # To update these lines, execute # `bazel run @contrib_rules_bazel_integration_test//tools:update_deleted_packages` -build --deleted_packages=examples/firebase_example,examples/http_archive_ext_deps,examples/http_archive_ext_deps/Sources/MyDequeModule,examples/http_archive_ext_deps/Sources/PrintStuff,examples/http_archive_ext_deps/Tests/MyDequeModuleTests,examples/http_archive_ext_deps/third_party,examples/interesting_deps,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/objc_code,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example -query --deleted_packages=examples/firebase_example,examples/http_archive_ext_deps,examples/http_archive_ext_deps/Sources/MyDequeModule,examples/http_archive_ext_deps/Sources/PrintStuff,examples/http_archive_ext_deps/Tests/MyDequeModuleTests,examples/http_archive_ext_deps/third_party,examples/interesting_deps,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/objc_code,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example +build --deleted_packages=examples/firebase_example,examples/firebase_example/analytics/AnalyticsExample,examples/http_archive_ext_deps,examples/http_archive_ext_deps/Sources/MyDequeModule,examples/http_archive_ext_deps/Sources/PrintStuff,examples/http_archive_ext_deps/Tests/MyDequeModuleTests,examples/http_archive_ext_deps/third_party,examples/interesting_deps,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/objc_code,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example +query --deleted_packages=examples/firebase_example,examples/firebase_example/analytics/AnalyticsExample,examples/http_archive_ext_deps,examples/http_archive_ext_deps/Sources/MyDequeModule,examples/http_archive_ext_deps/Sources/PrintStuff,examples/http_archive_ext_deps/Tests/MyDequeModuleTests,examples/http_archive_ext_deps/third_party,examples/interesting_deps,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/objc_code,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example # Import Shared settings import %workspace%/shared.bazelrc diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel index 3baccccae..49bbe4c39 100644 --- a/examples/BUILD.bazel +++ b/examples/BUILD.bazel @@ -27,10 +27,11 @@ _all_os_single_bazel_version_test_examples = [ ] _macos_single_bazel_version_test_examples = [ + "firebase_example", + "interesting_deps", "ios_sim", "objc_code", "xcmetrics_example", - "interesting_deps", ] # The default timeout is "long". diff --git a/examples/firebase_example/.bazelrc b/examples/firebase_example/.bazelrc index f1f3d97d5..958cc1926 100644 --- a/examples/firebase_example/.bazelrc +++ b/examples/firebase_example/.bazelrc @@ -15,7 +15,3 @@ build --cxxopt='-std=c++14' # Firebase SPM support requires `-ObjC` linker option. # https://github.com/firebase/firebase-ios-sdk/blob/master/SwiftPackageManager.md#requirements build --linkopt='-ObjC' - -# Since this project is not building a ios_application or ios_unit_test, we need to specify an Apple platform. -# https://github.com/bazelbuild/rules_swift/issues/240#issuecomment-708885118 -build --apple_platform_type=ios diff --git a/examples/firebase_example/BUILD.bazel b/examples/firebase_example/BUILD.bazel index be7f74a2d..960d07d36 100644 --- a/examples/firebase_example/BUILD.bazel +++ b/examples/firebase_example/BUILD.bazel @@ -40,37 +40,3 @@ bzl_library( visibility = ["//visibility:public"], deps = ["@cgrindel_swift_bazel//swiftpkg:defs"], ) - -# List the build_test targets defined in the package: -# bazel query 'kind(_empty_test, @swiftpkg_firebase_ios_sdk//...)' -test_suite( - name = "xcode_metrics_package_build_tests", - tests = [ - "@swiftpkg_firebase_ios_sdk//:FirebaseAnalyticsBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseAnalyticsSwift-BetaBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseAnalyticsWithoutAdIdSupportBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseAppCheckBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseAppDistribution-BetaBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseAuthBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseAuthCombine-CommunityBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseCrashlyticsBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseDatabaseBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseDatabaseSwift-BetaBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseDynamicLinksBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseFirestoreBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseFirestoreCombine-CommunityBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseFirestoreSwift-BetaBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseFunctionsBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseFunctionsCombine-CommunityBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseInAppMessaging-BetaBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseInAppMessagingSwift-BetaBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseInstallationsBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseMLModelDownloaderBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseMessagingBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebasePerformanceBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseRemoteConfigBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseStorageBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseStorageCombine-CommunityBuildTest", - "@swiftpkg_firebase_ios_sdk//:FirebaseStorageSwift-BetaBuildTest", - ], -) diff --git a/examples/firebase_example/README.md b/examples/firebase_example/README.md new file mode 100644 index 000000000..a61ab1899 --- /dev/null +++ b/examples/firebase_example/README.md @@ -0,0 +1,6 @@ +# Firebase iOS SDK Example + +The targets in this example were copied/inspired by the [Firebase iOS quickstart examples](https://github.com/firebase/quickstart-ios). + +The [Firebase iOS SDK](https://github.com/firebase/firebase-ios-sdk) is interesting as it directly +and indirectly exercises unique Swift package manifests. diff --git a/examples/firebase_example/analytics/AnalyticsExample/AnalyticsExample.entitlements b/examples/firebase_example/analytics/AnalyticsExample/AnalyticsExample.entitlements new file mode 100644 index 000000000..8cc185af8 --- /dev/null +++ b/examples/firebase_example/analytics/AnalyticsExample/AnalyticsExample.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.cs.disable-library-validation + + + diff --git a/examples/firebase_example/analytics/AnalyticsExample/AnalyticsView.swift b/examples/firebase_example/analytics/AnalyticsExample/AnalyticsView.swift new file mode 100644 index 000000000..a51d491c0 --- /dev/null +++ b/examples/firebase_example/analytics/AnalyticsExample/AnalyticsView.swift @@ -0,0 +1,349 @@ +// 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 UIKit + +/// Represents the main view shown in AnalyticsViewController. +final class AnalyticsView: UIScrollView { + // MARK: - UI Properties & Controls + + public var seasonPicker: UISegmentedControl! + + public var seasonImageView: UIImageView! + + public var preferredUnitsPicker: UISegmentedControl! + + public var preferredConditionsPicker: UISegmentedControl! + + public var preferredTemperatureFeelPicker: UISegmentedControl! + + public var sliderTemperatureLabel: UILabel! + + public lazy var postButton: UIButton = { + let button = UIButton() + button.setTitle("Post about the weather", for: .normal) + button.setTitleColor(UIColor.white.highlighted, for: .highlighted) + button.setBackgroundImage(UIColor.systemOrange.image, for: .normal) + button.setBackgroundImage(UIColor.systemOrange.highlighted.image, for: .highlighted) + button.clipsToBounds = true + button.layer.cornerRadius = 16 + button.backgroundColor = .systemOrange + return button + }() + + public lazy var temperatureSlider: UISlider = { + let slider = UISlider() + slider.minimumTrackTintColor = .systemGray + slider.minimumValue = 0 + slider.maximumValue = 100 + return slider + }() + + // MARK: Auxillary Views for Layout Purposes + + private var descriptionLabel: UILabel! + + private var userPropertiesLabel: UILabel! + + private var unitsLabel: UILabel! + + private var logEventsLabel: UILabel! + + private var preferredTemperatureFeelLabel: UILabel! + + private var preferredConditionsPickerLabel: UILabel! + + private var preferredTemperatureLabel: UILabel! + + private var imageViewBackgroundView: UIView! + + private var backgroundLabel: UILabel! + + // MARK: Private Layout Convenience Properties + + private let xOrigin: CGFloat = 15 + private var insetWidth: CGFloat { frame.width - 30 } + private var height: CGFloat { frame.height } + + // MARK: - Initializers + + override init(frame: CGRect) { + super.init(frame: frame) + contentInsetAdjustmentBehavior = .never + backgroundColor = .systemBackground + setupSubviews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Subviews Setup + + private func setupSubviews() { + /// Adds a description label under navigation bar. + descriptionLabel = buildLabel( + text: "Interact with the various controls to start collecting analytics data.", + textColor: .secondaryLabel, numberOfLines: 2 + ) + addSubview(descriptionLabel) + + // MARK: - User Properties Controls + + /// Label for the `Set user properties` section. + userPropertiesLabel = buildLabel( + text: "Set user properties", + font: .preferredFont(forTextStyle: .title3) + ) + addSubview(userPropertiesLabel) + + // MARK: - User's Favorite Season UISegmentedControl & UIImageView + + /// Adds a `UISegmentedControl` so users can select their favorite season. + seasonPicker = UISegmentedControl(items: ["Spring", "Summer", "Autumn", "Winter"]) + seasonPicker.translatesAutoresizingMaskIntoConstraints = false + addSubview(seasonPicker) + + /// Sets up the `UIImageView` for the `seasonPicker`. + setupImageViewSection() + + // MARK: - Preferred Temperature Units (°C or °F) UISegmentedControl + + /// Static `UILabel` associated with `preferredTemperatureFeelPicker`. + unitsLabel = buildLabel(text: "Preferred Temperature Units:", textColor: .secondaryLabel) + addSubview(unitsLabel) + + /// Adds a `UISegmentedControl` so users can select their preferred temperature units. + preferredUnitsPicker = UISegmentedControl(items: ["°C", "°F"]) + addSubview(preferredUnitsPicker) + + // MARK: - Log Events Controls + + /// Label for the `Log user interactions with events` section. + logEventsLabel = buildLabel(text: "Log user interactions with events", + font: .preferredFont(forTextStyle: .title3)) + addSubview(logEventsLabel) + + // MARK: - Preferred Temperature Feel (Hot or Cold) UISegmentedControl + + /// Static `UILabel` associated with `preferredTemperatureFeelPicker`. + preferredTemperatureFeelLabel = buildLabel( + text: "Hot or cold weather?", + textColor: .secondaryLabel + ) + addSubview(preferredTemperatureFeelLabel) + + /// Adds a `UISegmentedControl` so users can select from a pair of weather conditions. + preferredTemperatureFeelPicker = UISegmentedControl(items: ["Hot", "Cold"]) + preferredTemperatureFeelPicker.translatesAutoresizingMaskIntoConstraints = false + addSubview(preferredTemperatureFeelPicker) + + // MARK: - Preferred Conditions (Rainy or Sunny) UISegmentedControl + + /// Static `UILabel` associated with `preferredConditionsPicker`. + preferredConditionsPickerLabel = buildLabel( + text: "Rainy or sunny days?", + textColor: .secondaryLabel + ) + addSubview(preferredConditionsPickerLabel) + + /// Adds a `UISegmentedControl` so users can select whether a day was `Rainy` or `Sunny`. + preferredConditionsPicker = UISegmentedControl(items: ["Rainy", "Sunny"]) + preferredConditionsPicker.translatesAutoresizingMaskIntoConstraints = false + addSubview(preferredConditionsPicker) + + // MARK: - Preferred Temperature UISlider + + /// Static `UILabel` associated with `temperatureSlider`. + preferredTemperatureLabel = buildLabel( + text: "Preferred temperature:", + textColor: .secondaryLabel + ) + addSubview(preferredTemperatureLabel) + + /// `UILabel` representing current value of `temperatureSlider`. + sliderTemperatureLabel = buildLabel( + text: "0°", + font: .boldSystemFont(ofSize: 22), + textColor: .label, + textAlignment: .right + ) + addSubview(sliderTemperatureLabel) + + /// A `UISlider` representing a user's preferred temperature. + addSubview(temperatureSlider) + + // MARK: - Post Button + + addSubview(postButton) + } + + /// Sets up an image view (and its support views) for diplaying seasons. + private func setupImageViewSection() { + /// Creates a background view that will be covered when an image is set to `seasonImageView`. + imageViewBackgroundView = UIView(frame: .zero) + imageViewBackgroundView.translatesAutoresizingMaskIntoConstraints = false + addSubview(imageViewBackgroundView) + imageViewBackgroundView.clipsToBounds = true + imageViewBackgroundView.layer.cornerRadius = 16 + imageViewBackgroundView.backgroundColor = .secondarySystemFill + + backgroundLabel = buildLabel( + text: "Set user properties when a user \nselects their favorite season ↑ or \n" + + "preferred temperature units ↓", + textColor: .secondaryLabel, numberOfLines: 3, textAlignment: .center + ) + addSubview(backgroundLabel) + + /// Create the UIImageView that can display a user's favorite season. + seasonImageView = UIImageView() + seasonImageView.translatesAutoresizingMaskIntoConstraints = false + addSubview(seasonImageView) + seasonImageView.contentMode = .scaleAspectFill + seasonImageView.clipsToBounds = true + seasonImageView.layer.cornerRadius = 16 + seasonImageView.backgroundColor = .clear + } + + /// Builds and returns a UILabel. + /// - Parameters: + /// - text: A String for the label's text property. + /// - font: A UIFont for the label's displayed text. + /// - textColor: The UIColor of the label's displayed text. + /// - numberOfLines: The number of lines available to display text content. + /// - textAlignment: The NSTextAligment used by the label to format it's text. + /// - Returns: A label that has been configured based on the passed in parameters. + private func buildLabel(text: String, font: UIFont = .preferredFont(forTextStyle: .body), + textColor: UIColor = .label, numberOfLines: Int = 1, + textAlignment: NSTextAlignment = .left) -> UILabel { + let label = UILabel() + label.translatesAutoresizingMaskIntoConstraints = false + label.text = text + label.font = font + label.textColor = textColor + label.numberOfLines = numberOfLines + label.textAlignment = textAlignment + return label + } + + override func layoutSubviews() { + super.layoutSubviews() + + descriptionLabel.frame = CGRect( + x: xOrigin, y: safeAreaInsets.top, + width: insetWidth, height: 50 + ) + userPropertiesLabel.frame = CGRect( + x: xOrigin, y: descriptionLabel.frame.maxY + padding(.element), + width: insetWidth, height: 25 + ) + seasonPicker.frame = CGRect( + x: xOrigin, y: userPropertiesLabel.frame.maxY + padding(.pair), + width: insetWidth, height: 40 + ) + imageViewBackgroundView.frame = CGRect( + x: xOrigin, y: seasonPicker.frame.maxY + padding(.pair), + width: insetWidth, height: 0.22 * height + ) + + backgroundLabel.sizeToFit() + backgroundLabel.center = imageViewBackgroundView.center + + seasonImageView.frame = CGRect( + x: xOrigin, y: seasonPicker.frame.maxY + padding(.pair), + width: insetWidth, height: 0.22 * height + ) + unitsLabel.frame = CGRect( + x: xOrigin, y: seasonImageView.frame.maxY + padding(.element), + width: insetWidth - 90, height: 30 + ) + preferredUnitsPicker.frame = CGRect( + x: frame.width - 95, y: seasonImageView.frame.maxY + padding(.element), + width: 80, height: 40 + ) + logEventsLabel.frame = CGRect( + x: xOrigin, y: unitsLabel.frame.maxY + padding(.element), + width: insetWidth, height: 25 + ) + preferredTemperatureFeelLabel.frame = CGRect( + x: xOrigin, y: logEventsLabel.frame.maxY + padding(.pair), + width: insetWidth - 75, height: 30 + ) + preferredTemperatureFeelPicker.frame = CGRect( + x: frame.width - 115, y: logEventsLabel.frame.maxY + padding(.pair), + width: 100, height: 40 + ) + preferredConditionsPickerLabel.frame = CGRect( + x: xOrigin, y: preferredTemperatureFeelPicker.frame.maxY + padding(.pair), + width: insetWidth - 75, height: 30 + ) + preferredConditionsPicker.frame = CGRect( + x: frame.width - 115, y: preferredConditionsPickerLabel.frame.minY, + width: 100, height: 40 + ) + preferredTemperatureLabel.frame = CGRect( + x: xOrigin, y: preferredConditionsPickerLabel.frame.maxY + 10, width: insetWidth - 75, + height: 30 + ) + sliderTemperatureLabel.frame = CGRect( + x: frame.width - 65, y: preferredConditionsPickerLabel.frame.maxY + 10, width: 50, height: 30 + ) + temperatureSlider.frame = CGRect( + origin: CGPoint(x: xOrigin, y: preferredTemperatureLabel.frame.maxY + padding(.section)), + size: CGSize(width: insetWidth, height: 20) + ) + + var maxY: CGFloat = temperatureSlider.frame.maxY + postButton.frame = CGRect( + x: 15, y: temperatureSlider.frame.maxY + padding(.section), + width: insetWidth, height: 45 + ) + maxY = postButton.frame.maxY + + // MARK: - Content Size + + /// Sets the appropriate `contentSize` of self (a `UIScrollview`) so the entire + /// content can scroll to fit on smaller screens. + contentSize = CGSize(width: frame.width, height: maxY + 20) + } + + // MARK: - Private Layout Helpers + + /// Represents different levels of spacing to pad UI Elements. + private enum Spacing { + case section + case element + case pair + } + + private func padding(_ spaceType: Spacing) -> CGFloat { + switch spaceType { + case .section: + return (0.03 * height) + case .element: + return (0.02 * height) + case .pair: + return (0.01 * height) + } + } +} + +extension UIColor { + var highlighted: UIColor { withAlphaComponent(0.8) } + + var image: UIImage { + let pixel = CGSize(width: 1, height: 1) + return UIGraphicsImageRenderer(size: pixel).image { context in + self.setFill() + context.fill(CGRect(origin: .zero, size: pixel)) + } + } +} diff --git a/examples/firebase_example/analytics/AnalyticsExample/AnalyticsViewController.swift b/examples/firebase_example/analytics/AnalyticsExample/AnalyticsViewController.swift new file mode 100644 index 000000000..981b4e9b7 --- /dev/null +++ b/examples/firebase_example/analytics/AnalyticsExample/AnalyticsViewController.swift @@ -0,0 +1,135 @@ +// 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. + +import UIKit +import FirebaseAnalytics + +class AnalyticsViewController: UIViewController { + private lazy var analyticsView = AnalyticsView(frame: view.frame) + + override func viewDidLoad() { + super.viewDidLoad() + configureNavigationBar() + view.addSubview(analyticsView) + analyticsView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + analyticsView.topAnchor.constraint(equalTo: view.topAnchor), + analyticsView.bottomAnchor.constraint(equalTo: view.bottomAnchor), + analyticsView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + analyticsView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + ]) + configureControls() + } + + // MARK: - Firebase 🔥 + + // MARK: Set User Properties + + @objc + private func seasonDidChange(_ control: UISegmentedControl) { + let season = control.titleForSegment(at: control.selectedSegmentIndex)! + analyticsView.seasonImageView.image = UIImage(named: season) + Analytics.setUserProperty(season, forName: "favorite_season") // 🔥 + } + + @objc + private func unitsDidChange(_ control: UISegmentedControl) { + let preferredUnits = control.titleForSegment(at: control.selectedSegmentIndex)! + Analytics.setUserProperty(preferredUnits, forName: "preferred_units") // 🔥 + } + + // MARK: Event Logging + + @objc + private func preferredTemperatureFeelDidChange(_ control: UISegmentedControl) { + let temperatureFeelPreference = control.titleForSegment(at: control.selectedSegmentIndex)! + Analytics.logEvent("hot_or_cold_switch", parameters: ["value": temperatureFeelPreference]) // 🔥 + } + + @objc + private func preferredConditionsDidChange(_ control: UISegmentedControl) { + let conditionsPreference = control.titleForSegment(at: control.selectedSegmentIndex)! + Analytics.logEvent("rainy_or_sunny_switch", parameters: ["value": conditionsPreference]) // 🔥 + } + + @objc + private func sliderDidChange(_ control: UISlider) { + let value = Int(control.value) + analyticsView.sliderTemperatureLabel.text = "\(value)°" + Analytics.logEvent("preferred_temperature_changed", parameters: ["preference": value]) // 🔥 + } + + @objc + private func buttonTapped() { + Analytics.logEvent("blog_button_tapped", parameters: nil) // 🔥 + let blogViewController = BlogViewController() + blogViewController.delegate = self + let navController = UINavigationController(rootViewController: blogViewController) + navigationController?.present(navController, animated: true) + } + + // MARK: - Private Helpers + + private func configureControls() { + analyticsView.seasonPicker.addTarget( + self, + action: #selector(seasonDidChange(_:)), + for: .valueChanged + ) + + analyticsView.preferredUnitsPicker.addTarget( + self, + action: #selector(unitsDidChange(_:)), + for: .valueChanged + ) + + analyticsView.temperatureSlider.addTarget( + self, + action: #selector(sliderDidChange(_:)), + for: .valueChanged + ) + + analyticsView.preferredTemperatureFeelPicker.addTarget( + self, + action: #selector(preferredTemperatureFeelDidChange(_:)), + for: .valueChanged + ) + + analyticsView.preferredConditionsPicker.addTarget( + self, + action: #selector(preferredConditionsDidChange(_:)), + for: .valueChanged + ) + + analyticsView.postButton.addTarget( + self, + action: #selector(buttonTapped), + for: .touchUpInside + ) + } + + private func configureNavigationBar() { + navigationItem.title = "Firebase Analytics" + guard let navigationBar = navigationController?.navigationBar else { return } + navigationBar.prefersLargeTitles = true + navigationBar.titleTextAttributes = [.foregroundColor: UIColor.systemOrange] + navigationBar.largeTitleTextAttributes = [.foregroundColor: UIColor.systemOrange] + } +} + +extension AnalyticsViewController: BlogViewControllerDelegate { + func dismiss(animated: Bool) { + navigationController?.dismiss(animated: animated, completion: nil) + } +} diff --git a/examples/firebase_example/analytics/AnalyticsExample/AppDelegate.swift b/examples/firebase_example/analytics/AnalyticsExample/AppDelegate.swift new file mode 100644 index 000000000..a4b5592ac --- /dev/null +++ b/examples/firebase_example/analytics/AnalyticsExample/AppDelegate.swift @@ -0,0 +1,39 @@ +// 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. + +import UIKit +import FirebaseCore + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + func application(_ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication + .LaunchOptionsKey: Any]?) -> Bool { + FirebaseApp.configure() + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, + configurationForConnecting connectingSceneSession: UISceneSession, + options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration( + name: "Default Configuration", + sessionRole: connectingSceneSession.role + ) + } +} diff --git a/examples/firebase_example/analytics/AnalyticsExample/BUILD.bazel b/examples/firebase_example/analytics/AnalyticsExample/BUILD.bazel new file mode 100644 index 000000000..e99e47384 --- /dev/null +++ b/examples/firebase_example/analytics/AnalyticsExample/BUILD.bazel @@ -0,0 +1,38 @@ +load("@bazel_skylib//rules:build_test.bzl", "build_test") +load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application") +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "AnalyticsExample", + srcs = [ + "AnalyticsView.swift", + "AnalyticsViewController.swift", + "AppDelegate.swift", + "BlogViewController.swift", + "SceneDelegate.swift", + ], + module_name = "AnalyticsExample", + tags = ["manual"], + visibility = ["//visibility:public"], + deps = ["@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseAnalyticsWithoutAdIdSupportWrap_FirebaseAnalyticsWithoutAdIdSupportTarget"], +) + +ios_application( + name = "iosapp", + bundle_id = "com.google.firebase.quickstart.AnalyticsExample", + families = [ + "iphone", + "ipad", + ], + infoplists = [":Info.plist"], + launch_storyboard = "//analytics/AnalyticsExample:Base.lproj/LaunchScreen.storyboard", + minimum_os_version = "13.0", + deps = [":AnalyticsExample"], +) + +build_test( + name = "iosapp_build_test", + targets = [ + ":iosapp", + ], +) diff --git a/examples/firebase_example/analytics/AnalyticsExample/Base.lproj/LaunchScreen.storyboard b/examples/firebase_example/analytics/AnalyticsExample/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..dfcb6cf9f --- /dev/null +++ b/examples/firebase_example/analytics/AnalyticsExample/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/firebase_example/analytics/AnalyticsExample/BlogViewController.swift b/examples/firebase_example/analytics/AnalyticsExample/BlogViewController.swift new file mode 100644 index 000000000..301c62d5b --- /dev/null +++ b/examples/firebase_example/analytics/AnalyticsExample/BlogViewController.swift @@ -0,0 +1,155 @@ +// 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. + +import UIKit +import FirebaseAnalytics + +/// Used for view controller dismissal on MacCatalyst. +@objc +protocol BlogViewControllerDelegate { + func dismiss(animated: Bool) +} + +/// The `BlogViewController` demonstrates how to set a custom screen name for analytics tracking. +class BlogViewController: UIViewController, UITextViewDelegate { + var delegate: BlogViewControllerDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + configureNavigationBar() + view.backgroundColor = .systemBackground + setupSubviews() + + // Log the event appearing, adding the appropriate keys and values needed + // for screen view events. 🔥 + let parameters = [ + AnalyticsParameterScreenName: "BlogViewController", + AnalyticsParameterScreenClass: "class", + ] + Analytics.logEvent(AnalyticsEventScreenView, parameters: parameters) + } + + // MARK: - Private Helpers + + @objc + private func buttonTapped() { + // For demo purposes, the blog post is not really saved. However, the tap event is logged with Firebase Analytics. + Analytics.logEvent("blog_saved", parameters: nil) // 🔥 + } + + private var doneButton: UIBarButtonItem { + #if targetEnvironment(macCatalyst) + UIBarButtonItem( + barButtonSystemItem: .close, + target: self, + action: #selector(dismissBlogViewController) + ) + #else + UIBarButtonItem( + barButtonSystemItem: .done, + target: self, + action: #selector(dismissKeyboardOnTap) + ) + #endif // !targetEnvironment(macCatalyst) + } + + @objc + func dismissBlogViewController() { + delegate?.dismiss(animated: true) + } + + private func configureNavigationBar() { + navigationItem.title = "Weather Blog" + guard let navigationBar = navigationController?.navigationBar else { return } + navigationBar.prefersLargeTitles = true + navigationBar.titleTextAttributes = [.foregroundColor: UIColor.systemOrange] + navigationBar.largeTitleTextAttributes = [.foregroundColor: UIColor.systemOrange] + } + + private func setupSubviews() { + let description = UILabel() + view.addSubview(description) + description.text = "See the code to see how to set custom screen names for analytics tracking." + description.textColor = .secondaryLabel + description.numberOfLines = 2 + + let button = UIButton() + view.addSubview(button) + button.setTitle("Save Blog Post", for: .normal) + button.setTitleColor(UIColor.white.highlighted, for: .highlighted) + button.setBackgroundImage(UIColor.systemOrange.image, for: .normal) + button.setBackgroundImage(UIColor.systemOrange.highlighted.image, for: .highlighted) + button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) + button.clipsToBounds = true + button.layer.cornerRadius = 16 + button.backgroundColor = .systemOrange + + let textView = UITextView() + view.addSubview(textView) + textView.contentInset = UIEdgeInsets(top: 10, left: 10, bottom: -20, right: -20) + textView.text = "Today, the weather was ... " + textView.font = .preferredFont(forTextStyle: .body) + textView.backgroundColor = .secondarySystemFill + textView.layer.cornerRadius = 16 + textView.delegate = self + + // Manual frame layout. + + #if targetEnvironment(macCatalyst) + description.frame = CGRect( + x: 17, y: navigationController!.navigationBar.frame.maxY + 50, + width: view.frame.width * 0.30, height: 50 + ) + button.frame = CGRect( + x: 15, y: view.frame.height * 0.68, + width: view.frame.width * 0.33, height: 45 + ) + textView.frame = CGRect( + x: 15, y: description.frame.maxY + 13, + width: view.frame.width * 0.33, height: view.frame.height * 0.45 + ) + #else + description.frame = CGRect( + x: 15, y: navigationController!.navigationBar.frame.maxY, + width: view.frame.width - 30, height: 50 + ) + button.frame = CGRect( + x: 15, y: view.frame.height * 0.83, + width: view.frame.width - 30, height: 45 + ) + textView.frame = CGRect( + x: 15, y: description.frame.maxY + 15, + width: view.frame.width - 30, height: view.frame.height * 0.50 + ) + #endif // targetEnvironment(macCatalyst) + } + + @objc + private func dismissKeyboardOnTap() { + view.endEditing(true) + navigationItem.rightBarButtonItem = nil + } + + // Dismisses keyboard when view is tapped. + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + super.touchesBegan(touches, with: event) + view.endEditing(true) + } + + // MARK: UITextViewDelegate + + func textViewDidBeginEditing(_ textView: UITextView) { + navigationItem.rightBarButtonItem = doneButton + } +} diff --git a/examples/firebase_example/analytics/AnalyticsExample/Info.plist b/examples/firebase_example/analytics/AnalyticsExample/Info.plist new file mode 100644 index 000000000..686752735 --- /dev/null +++ b/examples/firebase_example/analytics/AnalyticsExample/Info.plist @@ -0,0 +1,60 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + AnalyticsExample.SceneDelegate + + + + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/firebase_example/analytics/AnalyticsExample/SceneDelegate.swift b/examples/firebase_example/analytics/AnalyticsExample/SceneDelegate.swift new file mode 100644 index 000000000..97ee3a902 --- /dev/null +++ b/examples/firebase_example/analytics/AnalyticsExample/SceneDelegate.swift @@ -0,0 +1,33 @@ +// 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. + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, + options connectionOptions: UIScene.ConnectionOptions) { + guard let windowScene = (scene as? UIWindowScene) else { return } + window = UIWindow(windowScene: windowScene) + window? + .rootViewController = UINavigationController(rootViewController: AnalyticsViewController()) + window?.makeKeyAndVisible() + + #if targetEnvironment(macCatalyst) || os(macOS) + // Make sure all our controls are visible in the window. + windowScene.sizeRestrictions?.minimumSize = CGSize(width: 500, height: 800) + #endif + } +} diff --git a/examples/firebase_example/set_up_clean_test b/examples/firebase_example/set_up_clean_test index 9f0b97dd1..953f14e76 100755 --- a/examples/firebase_example/set_up_clean_test +++ b/examples/firebase_example/set_up_clean_test @@ -2,82 +2,5 @@ set -o errexit -o nounset -o pipefail -script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null && pwd)" - -# Remove all build files -find "${script_dir}" \ - -name "BUILD.bazel" \ - -not -path "${script_dir}/third_party/*" \ - -exec rm {} \; - -# Remove the SPM build folder -rm -rf .build - -# Replace the swift_deps.bzl with no declarations. -cat > "${script_dir}/swift_deps.bzl" <<-EOF -def swift_dependencies(): - pass -EOF - -# Add back a minimal build file at the root -cat > "${script_dir}/BUILD.bazel" <<-EOF -load("@bazel_gazelle//:def.bzl", "gazelle", "gazelle_binary") -load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -load("@bazel_skylib//rules:build_test.bzl", "build_test") -load("@cgrindel_bazel_starlib//bzltidy:defs.bzl", "tidy") -load("@cgrindel_swift_bazel//swiftpkg:defs.bzl", "swift_update_packages") - -tidy( - name = "tidy", - targets = [ - ":swift_update_pkgs", - ":update_build_files", - ], -) - -# MARK: - Gazelle - -# Ignore the Swift build folder -# gazelle:exclude .build - -gazelle_binary( - name = "gazelle_bin", - languages = [ - "@bazel_skylib_gazelle_plugin//bzl", - "@cgrindel_swift_bazel//gazelle", - ], -) - -gazelle( - name = "update_build_files", - gazelle = ":gazelle_bin", -) - -swift_update_packages( - name = "swift_update_pkgs", - gazelle = ":gazelle_bin", -) - -bzl_library( - name = "swift_deps", - srcs = ["swift_deps.bzl"], - visibility = ["//visibility:public"], - deps = ["@cgrindel_swift_bazel//swiftpkg:defs"], -) - -build_test( - name = "xcode_metrics_package_targets", - targets = [ - "@swiftpkg_xcmetrics//:XCMetrics", - "@swiftpkg_xcmetrics//:XCMetricsBackend", - ], -) - -test_suite( - name = "xcode_metrics_package_build_tests", - tests = [ - "@swiftpkg_xcmetrics//:XCMetricsClientBuildTest", - "@swiftpkg_xcmetrics//:XCMetricsUtilsBuildTest", - ], -) -EOF +# NOTE: This is a placeholder. The firebase examples do not support a clean +# test because some of the targets have been marked as 'manual'. diff --git a/examples/firebase_example/swift_deps_index.json b/examples/firebase_example/swift_deps_index.json index 6972e5662..864d43c43 100644 --- a/examples/firebase_example/swift_deps_index.json +++ b/examples/firebase_example/swift_deps_index.json @@ -1,712 +1,1241 @@ { + "direct_dep_identities": [ + "firebase-ios-sdk" + ], "modules": [ { "name": "build-test", "c99name": "build_test", "src_type": "clang", - "label": "@swiftpkg_abseil_cpp_swiftpm//:SwiftPMTests_build-test" + "label": "@swiftpkg_abseil_cpp_swiftpm//:SwiftPMTests_build-test", + "package_identity": "abseil-cpp-swiftpm", + "product_memberships": [] }, { "name": "abseil", "c99name": "abseil", "src_type": "clang", - "label": "@swiftpkg_abseil_cpp_swiftpm//:abseil" + "label": "@swiftpkg_abseil_cpp_swiftpm//:abseil", + "package_identity": "abseil-cpp-swiftpm", + "product_memberships": [ + "abseil" + ] }, { "name": "build-test", "c99name": "build_test", "src_type": "clang", - "label": "@swiftpkg_boringssl_swiftpm//:SwiftPMTests_build-test" + "label": "@swiftpkg_boringssl_swiftpm//:SwiftPMTests_build-test", + "package_identity": "boringssl-swiftpm", + "product_memberships": [] }, { "name": "openssl_grpc", "c99name": "openssl_grpc", "src_type": "clang", - "label": "@swiftpkg_boringssl_swiftpm//:openssl_grpc" + "label": "@swiftpkg_boringssl_swiftpm//:openssl_grpc", + "package_identity": "boringssl-swiftpm", + "product_memberships": [ + "openssl_grpc" + ] }, { "name": "Firebase", "c99name": "Firebase", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:CoreOnly_Sources_Firebase" + "label": "@swiftpkg_firebase_ios_sdk//:CoreOnly_Sources_Firebase", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAnalytics", + "FirebaseAnalyticsWithoutAdIdSupport", + "FirebaseAnalyticsSwift-Beta", + "FirebaseAuth", + "FirebaseAppCheck", + "FirebaseAppDistribution-Beta", + "FirebaseAuthCombine-Community", + "FirebaseFirestoreCombine-Community", + "FirebaseFunctionsCombine-Community", + "FirebaseStorageCombine-Community", + "FirebaseCrashlytics", + "FirebaseDatabase", + "FirebaseDatabaseSwift-Beta", + "FirebaseDynamicLinks", + "FirebaseFirestore", + "FirebaseFirestoreSwift-Beta", + "FirebaseFunctions", + "FirebaseInAppMessaging-Beta", + "FirebaseInAppMessagingSwift-Beta", + "FirebaseInstallations", + "FirebaseMessaging", + "FirebaseMLModelDownloader", + "FirebasePerformance", + "FirebaseRemoteConfig", + "FirebaseStorage", + "FirebaseStorageSwift-Beta" + ] }, { "name": "FirebaseCrashlytics", "c99name": "FirebaseCrashlytics", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:Crashlytics_FirebaseCrashlytics" + "label": "@swiftpkg_firebase_ios_sdk//:Crashlytics_FirebaseCrashlytics", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseCrashlytics" + ] }, { "name": "FirebaseABTesting", "c99name": "FirebaseABTesting", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseABTesting_Sources_FirebaseABTesting" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseABTesting_Sources_FirebaseABTesting", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseInAppMessaging-Beta", + "FirebaseInAppMessagingSwift-Beta", + "FirebasePerformance", + "FirebaseRemoteConfig" + ] }, { "name": "ABTestingUnit", "c99name": "ABTestingUnit", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseABTesting_Tests_Unit_ABTestingUnit" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseABTesting_Tests_Unit_ABTestingUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseAnalyticsSwift", "c99name": "FirebaseAnalyticsSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAnalyticsSwift_Sources_FirebaseAnalyticsSwift" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAnalyticsSwift_Sources_FirebaseAnalyticsSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAnalyticsSwift-Beta" + ] }, { "name": "FirebaseAnalyticsWithoutAdIdSupportWrapper", "c99name": "FirebaseAnalyticsWithoutAdIdSupportWrapper", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAnalyticsWithoutAdIdSupportWrapper" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAnalyticsWithoutAdIdSupportWrapper", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAnalyticsWithoutAdIdSupport" + ] }, { "name": "FirebaseAnalyticsWrapper", "c99name": "FirebaseAnalyticsWrapper", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAnalyticsWrapper" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAnalyticsWrapper", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAnalytics", + "FirebaseAnalyticsSwift-Beta" + ] }, { "name": "FirebaseAppCheck", "c99name": "FirebaseAppCheck", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAppCheck_Sources_FirebaseAppCheck" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAppCheck_Sources_FirebaseAppCheck", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAppCheck" + ] }, { "name": "AppCheckUnit", "c99name": "AppCheckUnit", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAppCheck_Tests_AppCheckUnit" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAppCheck_Tests_AppCheckUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "AppCheckUnitSwift", "c99name": "AppCheckUnitSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAppCheck_Tests_Unit_Swift_AppCheckUnitSwift" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAppCheck_Tests_Unit_Swift_AppCheckUnitSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseAppDistribution", "c99name": "FirebaseAppDistribution", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAppDistribution_Sources_FirebaseAppDistribution" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAppDistribution_Sources_FirebaseAppDistribution", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAppDistribution-Beta" + ] }, { "name": "AppDistributionUnit", "c99name": "AppDistributionUnit", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAppDistribution_Tests_Unit_AppDistributionUnit" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAppDistribution_Tests_Unit_AppDistributionUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseAuth", "c99name": "FirebaseAuth", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAuth_Sources_FirebaseAuth" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAuth_Sources_FirebaseAuth", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAuth", + "FirebaseAuthCombine-Community" + ] }, { "name": "AuthUnit", "c99name": "AuthUnit", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAuth_Tests_Unit_AuthUnit" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseAuth_Tests_Unit_AuthUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseAuthCombineSwift", "c99name": "FirebaseAuthCombineSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCombineSwift_Sources_Auth_FirebaseAuthCombineSwift" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCombineSwift_Sources_Auth_FirebaseAuthCombineSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAuthCombine-Community" + ] }, { "name": "FirebaseFirestoreCombineSwift", "c99name": "FirebaseFirestoreCombineSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCombineSwift_Sources_Firestore_FirebaseFirestoreCombineSwift" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCombineSwift_Sources_Firestore_FirebaseFirestoreCombineSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseFirestoreCombine-Community" + ] }, { "name": "FirebaseFunctionsCombineSwift", "c99name": "FirebaseFunctionsCombineSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCombineSwift_Sources_Functions_FirebaseFunctionsCombineSwift" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCombineSwift_Sources_Functions_FirebaseFunctionsCombineSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseFunctionsCombine-Community" + ] }, { "name": "FirebaseStorageCombineSwift", "c99name": "FirebaseStorageCombineSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCombineSwift_Sources_Storage_FirebaseStorageCombineSwift" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCombineSwift_Sources_Storage_FirebaseStorageCombineSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseStorageCombine-Community" + ] }, { "name": "FirebaseCore", "c99name": "FirebaseCore", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCore_Sources_FirebaseCore" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCore_Sources_FirebaseCore", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAnalytics", + "FirebaseAnalyticsWithoutAdIdSupport", + "FirebaseAnalyticsSwift-Beta", + "FirebaseAuth", + "FirebaseAppCheck", + "FirebaseAppDistribution-Beta", + "FirebaseAuthCombine-Community", + "FirebaseFirestoreCombine-Community", + "FirebaseFunctionsCombine-Community", + "FirebaseStorageCombine-Community", + "FirebaseCrashlytics", + "FirebaseDatabase", + "FirebaseDatabaseSwift-Beta", + "FirebaseDynamicLinks", + "FirebaseFirestore", + "FirebaseFirestoreSwift-Beta", + "FirebaseFunctions", + "FirebaseInAppMessaging-Beta", + "FirebaseInAppMessagingSwift-Beta", + "FirebaseInstallations", + "FirebaseMessaging", + "FirebaseMLModelDownloader", + "FirebasePerformance", + "FirebaseRemoteConfig", + "FirebaseStorage", + "FirebaseStorageSwift-Beta" + ] }, { "name": "CoreUnit", "c99name": "CoreUnit", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCore_Tests_Unit_CoreUnit" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseCore_Tests_Unit_CoreUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseDatabaseSwift", "c99name": "FirebaseDatabaseSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDatabaseSwift_Sources_FirebaseDatabaseSwift" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDatabaseSwift_Sources_FirebaseDatabaseSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseDatabaseSwift-Beta" + ] }, { "name": "FirebaseDatabaseSwiftTests", "c99name": "FirebaseDatabaseSwiftTests", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDatabaseSwift_Tests_FirebaseDatabaseSwiftTests" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDatabaseSwift_Tests_FirebaseDatabaseSwiftTests", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseDatabase", "c99name": "FirebaseDatabase", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDatabase_Sources_FirebaseDatabase" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDatabase_Sources_FirebaseDatabase", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseDatabase", + "FirebaseDatabaseSwift-Beta" + ] }, { "name": "DatabaseUnit", "c99name": "DatabaseUnit", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDatabase_Tests_DatabaseUnit" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDatabase_Tests_DatabaseUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "DatabaseUnitSwift", "c99name": "DatabaseUnitSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDatabase_Tests_Unit_Swift_DatabaseUnitSwift" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDatabase_Tests_Unit_Swift_DatabaseUnitSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseDynamicLinks", "c99name": "FirebaseDynamicLinks", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDynamicLinks_Sources_FirebaseDynamicLinks" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseDynamicLinks_Sources_FirebaseDynamicLinks", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseDynamicLinks" + ] }, { "name": "FirebaseInAppMessaging", "c99name": "FirebaseInAppMessaging", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseInAppMessaging_Sources_FirebaseInAppMessaging" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseInAppMessaging_Sources_FirebaseInAppMessaging", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseInAppMessaging-Beta", + "FirebaseInAppMessagingSwift-Beta" + ] }, { "name": "FirebaseInAppMessagingSwift", "c99name": "FirebaseInAppMessagingSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseInAppMessaging_Swift_Source_FirebaseInAppMessagingSwift" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseInAppMessaging_Swift_Source_FirebaseInAppMessagingSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseInAppMessagingSwift-Beta" + ] }, { "name": "FirebaseInAppMessaging_iOS", "c99name": "FirebaseInAppMessaging_iOS", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseInAppMessaging_iOS_FirebaseInAppMessaging_iOS" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseInAppMessaging_iOS_FirebaseInAppMessaging_iOS", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseInAppMessaging-Beta", + "FirebaseInAppMessagingSwift-Beta" + ] }, { "name": "FirebaseInstallations", "c99name": "FirebaseInstallations", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseInstallations_Source_Library_FirebaseInstallations" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseInstallations_Source_Library_FirebaseInstallations", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAnalytics", + "FirebaseAnalyticsWithoutAdIdSupport", + "FirebaseAnalyticsSwift-Beta", + "FirebaseAppDistribution-Beta", + "FirebaseCrashlytics", + "FirebaseInAppMessaging-Beta", + "FirebaseInAppMessagingSwift-Beta", + "FirebaseInstallations", + "FirebaseMessaging", + "FirebaseMLModelDownloader", + "FirebasePerformance", + "FirebaseRemoteConfig" + ] }, { "name": "FirebaseMLModelDownloader", "c99name": "FirebaseMLModelDownloader", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseMLModelDownloader_Sources_FirebaseMLModelDownloader" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseMLModelDownloader_Sources_FirebaseMLModelDownloader", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseMLModelDownloader" + ] }, { "name": "FirebaseMLModelDownloaderUnit", "c99name": "FirebaseMLModelDownloaderUnit", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseMLModelDownloader_Tests_Unit_FirebaseMLModelDownloaderUnit" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseMLModelDownloader_Tests_Unit_FirebaseMLModelDownloaderUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseMessaging", "c99name": "FirebaseMessaging", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseMessaging_Sources_FirebaseMessaging" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseMessaging_Sources_FirebaseMessaging", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseMessaging" + ] }, { "name": "MessagingUnit", "c99name": "MessagingUnit", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseMessaging_Tests_UnitTests_MessagingUnit" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseMessaging_Tests_UnitTests_MessagingUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebasePerformance", "c99name": "FirebasePerformance", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebasePerformance_Sources_FirebasePerformance" + "label": "@swiftpkg_firebase_ios_sdk//:FirebasePerformance_Sources_FirebasePerformance", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebasePerformance" + ] }, { "name": "PerformanceUnit", "c99name": "PerformanceUnit", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebasePerformance_Tests_Unit_PerformanceUnit" + "label": "@swiftpkg_firebase_ios_sdk//:FirebasePerformance_Tests_Unit_PerformanceUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseRemoteConfig", "c99name": "FirebaseRemoteConfig", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseRemoteConfig_Sources_FirebaseRemoteConfig" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseRemoteConfig_Sources_FirebaseRemoteConfig", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebasePerformance", + "FirebaseRemoteConfig" + ] }, { "name": "RemoteConfigUnit", "c99name": "RemoteConfigUnit", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseRemoteConfig_Tests_Unit_RemoteConfigUnit" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseRemoteConfig_Tests_Unit_RemoteConfigUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseStorageSwift", "c99name": "FirebaseStorageSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseStorageSwift_Sources_FirebaseStorageSwift" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseStorageSwift_Sources_FirebaseStorageSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseStorageCombine-Community", + "FirebaseStorageSwift-Beta" + ] }, { "name": "FirebaseStorage", "c99name": "FirebaseStorage", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseStorage_Sources_FirebaseStorage" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseStorage_Sources_FirebaseStorage", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseStorageCombine-Community", + "FirebaseStorage", + "FirebaseStorageSwift-Beta" + ] }, { "name": "StorageUnit", "c99name": "StorageUnit", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseStorage_Tests_Unit_StorageUnit" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseStorage_Tests_Unit_StorageUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseFirestoreTestingSupport", "c99name": "FirebaseFirestoreTestingSupport", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseTestingSupport_Firestore_Sources_FirebaseFirestoreTestingSupport" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseTestingSupport_Firestore_Sources_FirebaseFirestoreTestingSupport", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirestoreTestingSupportTests", "c99name": "FirestoreTestingSupportTests", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseTestingSupport_Firestore_Tests_FirestoreTestingSupportTests" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseTestingSupport_Firestore_Tests_FirestoreTestingSupportTests", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseFunctionsTestingSupport", "c99name": "FirebaseFunctionsTestingSupport", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:FirebaseTestingSupport_Functions_Sources_FirebaseFunctionsTestingSupport" + "label": "@swiftpkg_firebase_ios_sdk//:FirebaseTestingSupport_Functions_Sources_FirebaseFunctionsTestingSupport", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseCoreDiagnostics", "c99name": "FirebaseCoreDiagnostics", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:Firebase_CoreDiagnostics_FIRCDLibrary_FirebaseCoreDiagnostics" + "label": "@swiftpkg_firebase_ios_sdk//:Firebase_CoreDiagnostics_FIRCDLibrary_FirebaseCoreDiagnostics", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAnalytics", + "FirebaseAnalyticsWithoutAdIdSupport", + "FirebaseAnalyticsSwift-Beta", + "FirebaseAuth", + "FirebaseAppCheck", + "FirebaseAppDistribution-Beta", + "FirebaseAuthCombine-Community", + "FirebaseFirestoreCombine-Community", + "FirebaseFunctionsCombine-Community", + "FirebaseStorageCombine-Community", + "FirebaseCrashlytics", + "FirebaseDatabase", + "FirebaseDatabaseSwift-Beta", + "FirebaseDynamicLinks", + "FirebaseFirestore", + "FirebaseFirestoreSwift-Beta", + "FirebaseFunctions", + "FirebaseInAppMessaging-Beta", + "FirebaseInAppMessagingSwift-Beta", + "FirebaseInstallations", + "FirebaseMessaging", + "FirebaseMLModelDownloader", + "FirebasePerformance", + "FirebaseRemoteConfig", + "FirebaseStorage", + "FirebaseStorageSwift-Beta" + ] }, { "name": "FirebaseFirestore", "c99name": "FirebaseFirestore", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:Firestore_FirebaseFirestore" + "label": "@swiftpkg_firebase_ios_sdk//:Firestore_FirebaseFirestore", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseFirestoreCombine-Community", + "FirebaseFirestore", + "FirebaseFirestoreSwift-Beta" + ] }, { "name": "FirebaseFirestoreSwift", "c99name": "FirebaseFirestoreSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:Firestore_FirebaseFirestoreSwift" + "label": "@swiftpkg_firebase_ios_sdk//:Firestore_FirebaseFirestoreSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseFirestoreCombine-Community", + "FirebaseFirestoreSwift-Beta" + ] }, { "name": "FunctionsUnit", "c99name": "FunctionsUnit", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:Functions_Example_Tests_FunctionsUnit" + "label": "@swiftpkg_firebase_ios_sdk//:Functions_Example_Tests_FunctionsUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseFunctions", "c99name": "FirebaseFunctions", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:Functions_FirebaseFunctions" + "label": "@swiftpkg_firebase_ios_sdk//:Functions_FirebaseFunctions", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseFunctionsCombine-Community", + "FirebaseFunctions" + ] }, { "name": "FunctionsCombineUnit", "c99name": "FunctionsCombineUnit", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:Functions_Tests_CombineUnit_FunctionsCombineUnit" + "label": "@swiftpkg_firebase_ios_sdk//:Functions_Tests_CombineUnit_FunctionsCombineUnit", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FunctionsUnitSwift", "c99name": "FunctionsUnitSwift", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:Functions_Tests_Unit_Swift_FunctionsUnitSwift" + "label": "@swiftpkg_firebase_ios_sdk//:Functions_Tests_Unit_Swift_FunctionsUnitSwift", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "SharedTestUtilities", "c99name": "SharedTestUtilities", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SharedTestUtilities" + "label": "@swiftpkg_firebase_ios_sdk//:SharedTestUtilities", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseAnalyticsSwiftTarget", "c99name": "FirebaseAnalyticsSwiftTarget", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseAnalyticsSwiftWrap_FirebaseAnalyticsSwiftTarget" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseAnalyticsSwiftWrap_FirebaseAnalyticsSwiftTarget", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAnalyticsSwift-Beta" + ] }, { "name": "FirebaseAnalyticsWithoutAdIdSupportTarget", "c99name": "FirebaseAnalyticsWithoutAdIdSupportTarget", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseAnalyticsWithoutAdIdSupportWrap_FirebaseAnalyticsWithoutAdIdSupportTarget" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseAnalyticsWithoutAdIdSupportWrap_FirebaseAnalyticsWithoutAdIdSupportTarget", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAnalyticsWithoutAdIdSupport" + ] }, { "name": "FirebaseAnalyticsTarget", "c99name": "FirebaseAnalyticsTarget", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseAnalyticsWrap_FirebaseAnalyticsTarget" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseAnalyticsWrap_FirebaseAnalyticsTarget", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAnalytics" + ] }, { "name": "FirebaseAppDistributionTarget", "c99name": "FirebaseAppDistributionTarget", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseAppDistributionWrap_FirebaseAppDistributionTarget" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseAppDistributionWrap_FirebaseAppDistributionTarget", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAppDistribution-Beta" + ] }, { "name": "FirebaseDynamicLinksTarget", "c99name": "FirebaseDynamicLinksTarget", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseDynamicLinksWrap_FirebaseDynamicLinksTarget" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseDynamicLinksWrap_FirebaseDynamicLinksTarget", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseDynamicLinks" + ] }, { "name": "FirebaseFirestoreSwiftTarget", "c99name": "FirebaseFirestoreSwiftTarget", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseFirestoreSwiftWrap_FirebaseFirestoreSwiftTarget" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseFirestoreSwiftWrap_FirebaseFirestoreSwiftTarget", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseFirestoreSwift-Beta" + ] }, { "name": "FirebaseFirestoreTarget", "c99name": "FirebaseFirestoreTarget", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseFirestoreWrap_FirebaseFirestoreTarget" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseFirestoreWrap_FirebaseFirestoreTarget", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseFirestore" + ] }, { "name": "FirebaseInAppMessagingTarget", "c99name": "FirebaseInAppMessagingTarget", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseInAppMessagingWrap_FirebaseInAppMessagingTarget" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseInAppMessagingWrap_FirebaseInAppMessagingTarget", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseInAppMessaging-Beta" + ] }, { "name": "FirebasePerformanceTarget", "c99name": "FirebasePerformanceTarget", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebasePerformanceWrap_FirebasePerformanceTarget" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebasePerformanceWrap_FirebasePerformanceTarget", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebasePerformance" + ] }, { "name": "analytics-import-test", "c99name": "analytics_import_test", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPMTests_analytics-import-test" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPMTests_analytics-import-test", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "objc-import-test", "c99name": "objc_import_test", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPMTests_objc-import-test" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPMTests_objc-import-test", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "swift-test", "c99name": "swift_test", "src_type": "swift", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPMTests_swift-test" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPMTests_swift-test", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "version-test", "c99name": "version_test", "src_type": "objc", - "label": "@swiftpkg_firebase_ios_sdk//:SwiftPMTests_version-test" + "label": "@swiftpkg_firebase_ios_sdk//:SwiftPMTests_version-test", + "package_identity": "firebase-ios-sdk", + "product_memberships": [] }, { "name": "FirebaseAnalytics", "c99name": "FirebaseAnalytics", - "src_type": "unknown", - "label": "@swiftpkg_firebase_ios_sdk//:remote_archive_FirebaseAnalytics.zip_FirebaseAnalytics" + "src_type": "binary", + "label": "@swiftpkg_firebase_ios_sdk//:remote_archive_FirebaseAnalytics.zip_FirebaseAnalytics", + "package_identity": "firebase-ios-sdk", + "product_memberships": [ + "FirebaseAnalytics", + "FirebaseAnalyticsWithoutAdIdSupport", + "FirebaseAnalyticsSwift-Beta" + ] }, { "name": "GoogleAppMeasurementWithoutAdIdSupportTarget", "c99name": "GoogleAppMeasurementWithoutAdIdSupportTarget", "src_type": "objc", - "label": "@swiftpkg_googleappmeasurement//:GoogleAppMeasurementWithoutAdIdSupportWrapper_GoogleAppMeasurementWithoutAdIdSupportTarget" + "label": "@swiftpkg_googleappmeasurement//:GoogleAppMeasurementWithoutAdIdSupportWrapper_GoogleAppMeasurementWithoutAdIdSupportTarget", + "package_identity": "googleappmeasurement", + "product_memberships": [ + "GoogleAppMeasurementWithoutAdIdSupport" + ] }, { "name": "GoogleAppMeasurementTarget", "c99name": "GoogleAppMeasurementTarget", "src_type": "objc", - "label": "@swiftpkg_googleappmeasurement//:GoogleAppMeasurementWrapper_GoogleAppMeasurementTarget" + "label": "@swiftpkg_googleappmeasurement//:GoogleAppMeasurementWrapper_GoogleAppMeasurementTarget", + "package_identity": "googleappmeasurement", + "product_memberships": [ + "GoogleAppMeasurement" + ] }, { "name": "GoogleAppMeasurement", "c99name": "GoogleAppMeasurement", - "src_type": "unknown", - "label": "@swiftpkg_googleappmeasurement//:remote_archive_GoogleAppMeasurement.zip_GoogleAppMeasurement" + "src_type": "binary", + "label": "@swiftpkg_googleappmeasurement//:remote_archive_GoogleAppMeasurement.zip_GoogleAppMeasurement", + "package_identity": "googleappmeasurement", + "product_memberships": [ + "GoogleAppMeasurement", + "GoogleAppMeasurementWithoutAdIdSupport" + ] }, { "name": "GoogleAppMeasurementIdentitySupport", "c99name": "GoogleAppMeasurementIdentitySupport", - "src_type": "unknown", - "label": "@swiftpkg_googleappmeasurement//:remote_archive_GoogleAppMeasurementIdentitySupport.zip_GoogleAppMeasurementIdentitySupport" + "src_type": "binary", + "label": "@swiftpkg_googleappmeasurement//:remote_archive_GoogleAppMeasurementIdentitySupport.zip_GoogleAppMeasurementIdentitySupport", + "package_identity": "googleappmeasurement", + "product_memberships": [ + "GoogleAppMeasurement" + ] }, { "name": "GoogleDataTransport", "c99name": "GoogleDataTransport", "src_type": "objc", - "label": "@swiftpkg_googledatatransport//:GoogleDataTransport" + "label": "@swiftpkg_googledatatransport//:GoogleDataTransport", + "package_identity": "googledatatransport", + "product_memberships": [ + "GoogleDataTransport" + ] }, { "name": "objc-import-test", "c99name": "objc_import_test", "src_type": "objc", - "label": "@swiftpkg_googledatatransport//:SwiftPMTests_objc-import-test" + "label": "@swiftpkg_googledatatransport//:SwiftPMTests_objc-import-test", + "package_identity": "googledatatransport", + "product_memberships": [] }, { "name": "swift-test", "c99name": "swift_test", "src_type": "swift", - "label": "@swiftpkg_googledatatransport//:SwiftPMTests_swift-test" + "label": "@swiftpkg_googledatatransport//:SwiftPMTests_swift-test", + "package_identity": "googledatatransport", + "product_memberships": [] }, { "name": "GoogleUtilities-Environment", "c99name": "GoogleUtilities_Environment", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:GoogleUtilities_Environment_GoogleUtilities-Environment" + "label": "@swiftpkg_googleutilities//:GoogleUtilities_Environment_GoogleUtilities-Environment", + "package_identity": "googleutilities", + "product_memberships": [ + "GULAppDelegateSwizzler", + "GULEnvironment", + "GULLogger", + "GULISASwizzler", + "GULMethodSwizzler", + "GULNetwork", + "GULReachability", + "GULSwizzlerTestHelpers", + "GULUserDefaults" + ] }, { "name": "GoogleUtilities-AppDelegateSwizzler", "c99name": "GoogleUtilities_AppDelegateSwizzler", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:GoogleUtilities_GoogleUtilities-AppDelegateSwizzler" + "label": "@swiftpkg_googleutilities//:GoogleUtilities_GoogleUtilities-AppDelegateSwizzler", + "package_identity": "googleutilities", + "product_memberships": [ + "GULAppDelegateSwizzler" + ] }, { "name": "GoogleUtilities-ISASwizzler", "c99name": "GoogleUtilities_ISASwizzler", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:GoogleUtilities_ISASwizzler_GoogleUtilities-ISASwizzler" + "label": "@swiftpkg_googleutilities//:GoogleUtilities_ISASwizzler_GoogleUtilities-ISASwizzler", + "package_identity": "googleutilities", + "product_memberships": [ + "GULISASwizzler" + ] }, { "name": "GoogleUtilities-Logger", "c99name": "GoogleUtilities_Logger", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:GoogleUtilities_Logger_GoogleUtilities-Logger" + "label": "@swiftpkg_googleutilities//:GoogleUtilities_Logger_GoogleUtilities-Logger", + "package_identity": "googleutilities", + "product_memberships": [ + "GULAppDelegateSwizzler", + "GULLogger", + "GULISASwizzler", + "GULMethodSwizzler", + "GULNetwork", + "GULReachability", + "GULSwizzlerTestHelpers", + "GULUserDefaults" + ] }, { "name": "GoogleUtilities-MethodSwizzler", "c99name": "GoogleUtilities_MethodSwizzler", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:GoogleUtilities_MethodSwizzler_GoogleUtilities-MethodSwizzler" + "label": "@swiftpkg_googleutilities//:GoogleUtilities_MethodSwizzler_GoogleUtilities-MethodSwizzler", + "package_identity": "googleutilities", + "product_memberships": [ + "GULMethodSwizzler", + "GULSwizzlerTestHelpers" + ] }, { "name": "GoogleUtilities-NSData", "c99name": "GoogleUtilities_NSData", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:GoogleUtilities_NSData+zlib_GoogleUtilities-NSData" + "label": "@swiftpkg_googleutilities//:GoogleUtilities_NSData+zlib_GoogleUtilities-NSData", + "package_identity": "googleutilities", + "product_memberships": [ + "GULAppDelegateSwizzler", + "GULNetwork", + "GULNSData" + ] }, { "name": "GoogleUtilities-Network", "c99name": "GoogleUtilities_Network", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:GoogleUtilities_Network_GoogleUtilities-Network" + "label": "@swiftpkg_googleutilities//:GoogleUtilities_Network_GoogleUtilities-Network", + "package_identity": "googleutilities", + "product_memberships": [ + "GULAppDelegateSwizzler", + "GULNetwork" + ] }, { "name": "GoogleUtilities-Reachability", "c99name": "GoogleUtilities_Reachability", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:GoogleUtilities_Reachability_GoogleUtilities-Reachability" + "label": "@swiftpkg_googleutilities//:GoogleUtilities_Reachability_GoogleUtilities-Reachability", + "package_identity": "googleutilities", + "product_memberships": [ + "GULAppDelegateSwizzler", + "GULNetwork", + "GULReachability" + ] }, { "name": "GoogleUtilities-SwizzlerTestHelpers", "c99name": "GoogleUtilities_SwizzlerTestHelpers", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:GoogleUtilities_SwizzlerTestHelpers_GoogleUtilities-SwizzlerTestHelpers" + "label": "@swiftpkg_googleutilities//:GoogleUtilities_SwizzlerTestHelpers_GoogleUtilities-SwizzlerTestHelpers", + "package_identity": "googleutilities", + "product_memberships": [ + "GULSwizzlerTestHelpers" + ] }, { "name": "UtilitiesUnit", "c99name": "UtilitiesUnit", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:GoogleUtilities_Tests_Unit_UtilitiesUnit" + "label": "@swiftpkg_googleutilities//:GoogleUtilities_Tests_Unit_UtilitiesUnit", + "package_identity": "googleutilities", + "product_memberships": [] }, { "name": "GoogleUtilities-UserDefaults", "c99name": "GoogleUtilities_UserDefaults", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:GoogleUtilities_UserDefaults_GoogleUtilities-UserDefaults" + "label": "@swiftpkg_googleutilities//:GoogleUtilities_UserDefaults_GoogleUtilities-UserDefaults", + "package_identity": "googleutilities", + "product_memberships": [ + "GULUserDefaults" + ] }, { "name": "objc-import-test", "c99name": "objc_import_test", "src_type": "objc", - "label": "@swiftpkg_googleutilities//:SwiftPMTests_objc-import-test" + "label": "@swiftpkg_googleutilities//:SwiftPMTests_objc-import-test", + "package_identity": "googleutilities", + "product_memberships": [] }, { "name": "swift-test", "c99name": "swift_test", "src_type": "swift", - "label": "@swiftpkg_googleutilities//:SwiftPMTests_swift-test" + "label": "@swiftpkg_googleutilities//:SwiftPMTests_swift-test", + "package_identity": "googleutilities", + "product_memberships": [] }, { "name": "build-test", "c99name": "build_test", "src_type": "clang", - "label": "@swiftpkg_grpc_swiftpm//:SwiftPMTests_build-test" + "label": "@swiftpkg_grpc_swiftpm//:SwiftPMTests_build-test", + "package_identity": "grpc-swiftpm", + "product_memberships": [] }, { "name": "gRPC-Core", "c99name": "gRPC_Core", "src_type": "clang", - "label": "@swiftpkg_grpc_swiftpm//:gRPC-Core" + "label": "@swiftpkg_grpc_swiftpm//:gRPC-Core", + "package_identity": "grpc-swiftpm", + "product_memberships": [ + "gRPC-Core", + "gRPC-cpp" + ] }, { "name": "gRPC-cpp", "c99name": "gRPC_cpp", "src_type": "clang", - "label": "@swiftpkg_grpc_swiftpm//:gRPC-cpp" + "label": "@swiftpkg_grpc_swiftpm//:gRPC-cpp", + "package_identity": "grpc-swiftpm", + "product_memberships": [ + "gRPC-cpp" + ] }, { "name": "GTMSessionFetcherCore", "c99name": "GTMSessionFetcherCore", "src_type": "objc", - "label": "@swiftpkg_gtm_session_fetcher//:Source_GTMSessionFetcherCore" + "label": "@swiftpkg_gtm_session_fetcher//:Source_GTMSessionFetcherCore", + "package_identity": "gtm-session-fetcher", + "product_memberships": [ + "GTMSessionFetcher", + "GTMSessionFetcherCore", + "GTMSessionFetcherFull", + "GTMSessionFetcherLogView" + ] }, { "name": "GTMSessionFetcherFull", "c99name": "GTMSessionFetcherFull", "src_type": "objc", - "label": "@swiftpkg_gtm_session_fetcher//:Source_GTMSessionFetcherFull" + "label": "@swiftpkg_gtm_session_fetcher//:Source_GTMSessionFetcherFull", + "package_identity": "gtm-session-fetcher", + "product_memberships": [ + "GTMSessionFetcher", + "GTMSessionFetcherFull" + ] }, { "name": "GTMSessionFetcherLogView", "c99name": "GTMSessionFetcherLogView", "src_type": "objc", - "label": "@swiftpkg_gtm_session_fetcher//:Source_GTMSessionFetcherLogView" + "label": "@swiftpkg_gtm_session_fetcher//:Source_GTMSessionFetcherLogView", + "package_identity": "gtm-session-fetcher", + "product_memberships": [ + "GTMSessionFetcherLogView" + ] }, { "name": "GTMSessionFetcherCoreTests", "c99name": "GTMSessionFetcherCoreTests", "src_type": "objc", - "label": "@swiftpkg_gtm_session_fetcher//:Source_UnitTests_GTMSessionFetcherCoreTests" + "label": "@swiftpkg_gtm_session_fetcher//:Source_UnitTests_GTMSessionFetcherCoreTests", + "package_identity": "gtm-session-fetcher", + "product_memberships": [] }, { "name": "leveldb", "c99name": "leveldb", "src_type": "clang", - "label": "@swiftpkg_leveldb//:leveldb" + "label": "@swiftpkg_leveldb//:leveldb", + "package_identity": "leveldb", + "product_memberships": [ + "leveldb" + ] }, { "name": "nanopb", "c99name": "nanopb", "src_type": "clang", - "label": "@swiftpkg_nanopb//:nanopb" + "label": "@swiftpkg_nanopb//:nanopb", + "package_identity": "nanopb", + "product_memberships": [ + "nanopb" + ] }, { "name": "objc-test", "c99name": "objc_test", "src_type": "objc", - "label": "@swiftpkg_nanopb//:spm-test_objc_objc-test" + "label": "@swiftpkg_nanopb//:spm-test_objc_objc-test", + "package_identity": "nanopb", + "product_memberships": [] }, { "name": "swift-test", "c99name": "swift_test", "src_type": "swift", - "label": "@swiftpkg_nanopb//:spm-test_swift_swift-test" + "label": "@swiftpkg_nanopb//:spm-test_swift_swift-test", + "package_identity": "nanopb", + "product_memberships": [] }, { "name": "FBLPromises", "c99name": "FBLPromises", "src_type": "objc", - "label": "@swiftpkg_promises//:Sources_FBLPromises" + "label": "@swiftpkg_promises//:Sources_FBLPromises", + "package_identity": "promises", + "product_memberships": [ + "FBLPromises", + "FBLPromisesTestHelpers", + "Promises", + "PromisesTestHelpers" + ] }, { "name": "FBLPromisesTestHelpers", "c99name": "FBLPromisesTestHelpers", "src_type": "objc", - "label": "@swiftpkg_promises//:Sources_FBLPromisesTestHelpers" + "label": "@swiftpkg_promises//:Sources_FBLPromisesTestHelpers", + "package_identity": "promises", + "product_memberships": [ + "FBLPromisesTestHelpers" + ] }, { "name": "Promises", "c99name": "Promises", "src_type": "swift", - "label": "@swiftpkg_promises//:Sources_Promises" + "label": "@swiftpkg_promises//:Sources_Promises", + "package_identity": "promises", + "product_memberships": [ + "Promises", + "PromisesTestHelpers" + ] }, { "name": "PromisesTestHelpers", "c99name": "PromisesTestHelpers", "src_type": "swift", - "label": "@swiftpkg_promises//:Sources_PromisesTestHelpers" + "label": "@swiftpkg_promises//:Sources_PromisesTestHelpers", + "package_identity": "promises", + "product_memberships": [ + "PromisesTestHelpers" + ] }, { "name": "FBLPromisesInteroperabilityTests", "c99name": "FBLPromisesInteroperabilityTests", "src_type": "objc", - "label": "@swiftpkg_promises//:Tests_FBLPromisesInteroperabilityTests" + "label": "@swiftpkg_promises//:Tests_FBLPromisesInteroperabilityTests", + "package_identity": "promises", + "product_memberships": [] }, { "name": "FBLPromisesPerformanceTests", "c99name": "FBLPromisesPerformanceTests", "src_type": "objc", - "label": "@swiftpkg_promises//:Tests_FBLPromisesPerformanceTests" + "label": "@swiftpkg_promises//:Tests_FBLPromisesPerformanceTests", + "package_identity": "promises", + "product_memberships": [] }, { "name": "FBLPromisesTests", "c99name": "FBLPromisesTests", "src_type": "objc", - "label": "@swiftpkg_promises//:Tests_FBLPromisesTests" + "label": "@swiftpkg_promises//:Tests_FBLPromisesTests", + "package_identity": "promises", + "product_memberships": [] }, { "name": "PromisesInteroperabilityTests", "c99name": "PromisesInteroperabilityTests", "src_type": "swift", - "label": "@swiftpkg_promises//:Tests_PromisesInteroperabilityTests" + "label": "@swiftpkg_promises//:Tests_PromisesInteroperabilityTests", + "package_identity": "promises", + "product_memberships": [] }, { "name": "PromisesPerformanceTests", "c99name": "PromisesPerformanceTests", "src_type": "swift", - "label": "@swiftpkg_promises//:Tests_PromisesPerformanceTests" + "label": "@swiftpkg_promises//:Tests_PromisesPerformanceTests", + "package_identity": "promises", + "product_memberships": [] }, { "name": "PromisesTests", "c99name": "PromisesTests", "src_type": "swift", - "label": "@swiftpkg_promises//:Tests_PromisesTests" + "label": "@swiftpkg_promises//:Tests_PromisesTests", + "package_identity": "promises", + "product_memberships": [] }, { "name": "SwiftProtobufPlugin", "c99name": "SwiftProtobufPlugin", "src_type": "unknown", - "label": "@swiftpkg_swift_protobuf//:Plugins_SwiftProtobufPlugin" + "label": "@swiftpkg_swift_protobuf//:Plugins_SwiftProtobufPlugin", + "package_identity": "swift-protobuf", + "product_memberships": [ + "SwiftProtobufPlugin" + ] }, { "name": "Conformance", "c99name": "Conformance", "src_type": "swift", - "label": "@swiftpkg_swift_protobuf//:Sources_Conformance" + "label": "@swiftpkg_swift_protobuf//:Sources_Conformance", + "package_identity": "swift-protobuf", + "product_memberships": [ + "Conformance" + ] }, { "name": "SwiftProtobuf", "c99name": "SwiftProtobuf", "src_type": "swift", - "label": "@swiftpkg_swift_protobuf//:Sources_SwiftProtobuf" + "label": "@swiftpkg_swift_protobuf//:Sources_SwiftProtobuf", + "package_identity": "swift-protobuf", + "product_memberships": [ + "protoc-gen-swift", + "SwiftProtobuf", + "SwiftProtobufPluginLibrary", + "SwiftProtobufPlugin", + "Conformance" + ] }, { "name": "SwiftProtobufPluginLibrary", "c99name": "SwiftProtobufPluginLibrary", "src_type": "swift", - "label": "@swiftpkg_swift_protobuf//:Sources_SwiftProtobufPluginLibrary" + "label": "@swiftpkg_swift_protobuf//:Sources_SwiftProtobufPluginLibrary", + "package_identity": "swift-protobuf", + "product_memberships": [ + "protoc-gen-swift", + "SwiftProtobufPluginLibrary", + "SwiftProtobufPlugin" + ] }, { "name": "protoc-gen-swift", "c99name": "protoc_gen_swift", "src_type": "swift", - "label": "@swiftpkg_swift_protobuf//:Sources_protoc-gen-swift" + "label": "@swiftpkg_swift_protobuf//:Sources_protoc-gen-swift", + "package_identity": "swift-protobuf", + "product_memberships": [ + "protoc-gen-swift", + "SwiftProtobufPlugin" + ] }, { "name": "SwiftProtobufPluginLibraryTests", "c99name": "SwiftProtobufPluginLibraryTests", "src_type": "swift", - "label": "@swiftpkg_swift_protobuf//:Tests_SwiftProtobufPluginLibraryTests" + "label": "@swiftpkg_swift_protobuf//:Tests_SwiftProtobufPluginLibraryTests", + "package_identity": "swift-protobuf", + "product_memberships": [] }, { "name": "SwiftProtobufTests", "c99name": "SwiftProtobufTests", "src_type": "swift", - "label": "@swiftpkg_swift_protobuf//:Tests_SwiftProtobufTests" + "label": "@swiftpkg_swift_protobuf//:Tests_SwiftProtobufTests", + "package_identity": "swift-protobuf", + "product_memberships": [] } ], "products": [