{"id":13872008,"url":"https://github.com/Flowductive/easy-firebase","last_synced_at":"2025-07-16T01:32:36.291Z","repository":{"id":37245323,"uuid":"422434354","full_name":"Flowductive/easy-firebase","owner":"Flowductive","description":"🔥 A Swifty solution for all things Firebase. Quickly implement Firestore and Authentication on iOS + macOS using Swift protocols and methods.","archived":true,"fork":false,"pushed_at":"2024-03-29T05:41:08.000Z","size":85876,"stargazers_count":76,"open_issues_count":13,"forks_count":7,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-10-06T01:46:10.918Z","etag":null,"topics":["authentication","cloud-messaging","firebase","firebase-auth","firebase-storage","firestore","ios","macos","push-notifications","sign-in-with-apple","sign-in-with-google","signinwithapple","signinwithgoogle","storage","swift","swift-5","swift5","swiftui","uikit"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Flowductive.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-29T03:49:11.000Z","updated_at":"2024-09-23T03:09:36.000Z","dependencies_parsed_at":"2023-02-19T14:00:43.615Z","dependency_job_id":null,"html_url":"https://github.com/Flowductive/easy-firebase","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flowductive%2Feasy-firebase","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flowductive%2Feasy-firebase/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flowductive%2Feasy-firebase/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Flowductive%2Feasy-firebase/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Flowductive","download_url":"https://codeload.github.com/Flowductive/easy-firebase/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225065621,"owners_count":17415485,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","cloud-messaging","firebase","firebase-auth","firebase-storage","firestore","ios","macos","push-notifications","sign-in-with-apple","sign-in-with-google","signinwithapple","signinwithgoogle","storage","swift","swift-5","swift5","swiftui","uikit"],"created_at":"2024-08-05T23:00:32.237Z","updated_at":"2024-11-23T19:31:31.798Z","avatar_url":"https://github.com/Flowductive.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"![Social Preview](./Assets/Social%20Preview%20(640).png)\n\n\u003ch2 align=\"center\"\u003eFirebase for iOS and macOS made easy.\u003c/h2\u003e\n\n\u003cp align=\"center\"\u003e🍏 Third-party authentication done in a single line of code\u003c/p\u003e\n\u003cp align=\"center\"\u003e✉️ Send and receive Firestore documents in a snap\u003c/p\u003e\n\u003cp align=\"center\"\u003e😀 Predefined user protocols with built-in features\u003c/p\u003e\n\u003cp align=\"center\"\u003e🔥 Firebase solutions in one native Swift package\u003c/p\u003e\n\u003cp align=\"center\"\u003e📘 Fully documented code with examples\u003c/p\u003e\n\n***\n\n⚠️ **Note:** This package is still under development and its contents are freely subject to change.\n\n📚 **Ready to get started?** Check out our [complete wiki](https://github.com/Flowductive/easy-firebase/wiki) for detailed guides.\n\n![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Flowductive/easy-firebase?label=version)\n![GitHub Release Date](https://img.shields.io/github/release-date/Flowductive/easy-firebase?label=latest%20release)\n![GitHub issues](https://img.shields.io/github/issues/Flowductive/easy-firebase)\n![GitHub pull requests](https://img.shields.io/github/issues-pr/Flowductive/easy-firebase)\n\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FFlowductive%2Feasy-firebase%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/Flowductive/easy-firebase)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FFlowductive%2Feasy-firebase%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/Flowductive/easy-firebase)\n\n## What is EasyFirebase?\n\nEasyFirebase is a Swift wrapper for all things Firebase. Save hours from implementing the Firebase code in your projects repeatedly. EasyFirebase makes document storage and retrieval easier by providing **intuitive protocols** for Firestore. EasyFirebase makes **authentication easier** with the EasyUser (subclassable) open class and simple one-line sign-in with Google and Apple. EasyFirebase is cross-platform and works with both iOS and macOS.\n\n## Completed Features\n\n- Firestore Support\n  - Built-in Document protocol [→](https://github.com/Flowductive/easy-firebase#built-in-document-protocol)\n  - Document storage [→](https://github.com/Flowductive/easy-firebase#document-storage)\n  - Document removal\n  - Document retrieval [→](https://github.com/Flowductive/easy-firebase#document-retrieval)\n  - ✨ NEW: Document updating [→](https://github.com/Flowductive/easy-firebase#document-updating)\n  - Update listeners [→](https://github.com/Flowductive/easy-firebase#update-listeners)\n  - Built-in cacheing [→](https://github.com/Flowductive/easy-firebase#built-in-cacheing)\n  - Easy linking [→](https://github.com/Flowductive/easy-firebase#easy-linking)\n  - Swifty querying [→](https://github.com/Flowductive/easy-firebase#swifty-querying)\n- Authentication Support\n  - EasyUser protocol [→](https://github.com/Flowductive/easy-firebase#easy-user-protocol)\n  - Email auth [→](https://github.com/Flowductive/easy-firebase#email-auth)\n  - Sign In with Google [→](https://github.com/Flowductive/easy-firebase#sign-in-with-google)\n  - Sign In with Apple [→](https://github.com/Flowductive/easy-firebase#sign-in-with-apple)\n  - Built-in usernames [→](https://github.com/Flowductive/easy-firebase#built-in-usernames)\n  - Robust user management [→](https://github.com/Flowductive/easy-firebase#robust-user-management)\n- Storage Support\n  - Data storage [→](https://github.com/Flowductive/easy-firebase#data-storage)\n  - Safe data overriding\n  - Data removal\n  - Data upload task visibility\n- Cloud Messaging Support\n  - Built-in user notifications [→](https://github.com/Flowductive/easy-firebase#built-in-user-notifications)\n  - Built-in MessagingNotification protocol\n  - Built-in 3P notifications\n  - User notification settings\n- Analytics Support\n  - Easily log events [→](https://github.com/Flowductive/easy-firebase#easily-log-events)\n  - Integrated user properties [→](https://github.com/Flowductive/easy-firebase#integrated-user-properties)\n\nAll the above features are **cross-platform** and are supported on both iOS and macOS.\n\n⭐️ This means EasyFirebase is the quickest way to implement Sign In with Google on macOS! ⭐️\n\n## Get Started\n\nAdd **EasyFirebase** to your project using Swift Package Manager:\n\n```\nhttps://github.com/Flowductive/easy-firebase\n```\n\nImport **EasyFirebase**:\n\n```swift\nimport EasyFirebase\n```\n\nConfigure at app launch:\n\n```swift\n// You don't need to call FirebaseApp.configure() when this is called!\nEasyFirebase.configure()\n```\n\n## 🔥 Firestore Feature Showcase\n\n### Built-in Document protocol\n\nSave time writing model classes with the built-in `Document` protocol:\n\n```swift\nclass Car: Document {\n  \n  // These properties are inherited from Document\n  var id: String = UUID().uuidString\n  var dateCreated: Date = Date()\n  \n  // Define your own custom properties\n  var make: String\n  var model: String\n  var year: Int\n  \n  init(make: String, model: String, year: Int) {\n    // ...\n  }\n}\n```\n\n### Document Storage\n\nStore documents anywhere in your code:\n\n```swift\nvar myCar = Car(make: \"Toyota\", model: \"Corolla\", year: 2017)\n\n// Store the car instance in the 'car' collection in Firestore\nmyCar.set()\n\n// Static method that does the same as above\nEasyFirestore.Storage.set(myCar)\n```\n\n### Document Retrieval\n\nGrab documents easily without needing to specify a collection name:\n\n```swift\nEasyFirestore.Retrieval.get(id: myCarID, ofType: Car.self) { car in\n  guard let car = car else { return }\n  self.myOtherCar = car\n}\n```\n\n### Document Updating\n\nUpdate fields remotely in Firestore without performing any reads.\n\n```swift\n// Append element to array\nEasyFirestore.Updating.append(\\.ingredients, with: \"Cheese\", in: pizzaDocument) { error in ... }\n\n// Increment field\nEasyFirestore.Updating.increment(\\.pepperoniCount, by: 5, in: pizzaDocument)\n\n// Remove elements from array\nEasyFirestore.Updating.remove(\\.ingredients, taking: [\"Garlic\", \"Anchovies\", \"Pineapple\"], from: pizzaDocument)\n```\n\n### Update Listeners\n\nGrab documents and update the local instance when changed in Firestore:\n\n```swift\nEasyFirestore.Listening.listen(to: otherCarID, ofType: Car.self, key: \"myCarListenerKey\") { car in\n  // Updates when changed in Firestore\n  guard let car = car else { return }\n  self.myOtherCar = car\n}\n```\n\n### Built-In Cacheing\n\nEasyFirestore will automatically cache fetched documents locally and will use the cached doucments when retrieving to reduce your Firestore read count.\n\n```swift\n// EasyFirebase will automatically cache fetched objects for you, here is a manual example\nEasyFirestore.Cacheing.register(myCar)\n\n// Get locally cached objects instantly. Retrieving objects using EasyFirestore.Retrieval will grab cached objects if they exist\nvar cachedCar = EasyFirestore.Cacheing.grab(myCarID, fromType: Car.self)\n```\n\n### Easy Linking\n\nLink child documents to an array of IDs in a parent document:\n\n```swift\nvar car1 = Car(make: \"Toyota\", model: \"Corolla\", year: 2017)\nvar car2 = Car(make: \"Honda\", model: \"Civic\", year: 2019)\n\nvar dealership = Dealership(name: \"Los Angeles Dealership\")\n\n// Set and assign the Toyota Corolla to the Los Angeles Dealership\ncar1.setAssign(toField: \"cars\", using: \\.cars, in: dealership)\n\n// Set and assign the Honda Civic to the Los Angeles Dealership\ncar2.set()\ncar2.assign(toField: \"cars\", using: \\.cars, in: dealership)\n```\n\n### Swifty Querying\n\nEasily query for documents:\n\n```swift\nEasyFirestore.Querying.where(\\Car.make, .equals, \"Toyota\") { cars in\n  // Handle your queried documents here...\n}\n```\n\nUse multiple conditions for queries; order and limit results:\n\n```swift\nEasyFirestore.Querying.where((\\Car.year, .greaterEqualTo, 2010),\n                             (\\Car.model, .in, [\"Corolla\", \"Camry\"]),\n                             order: .ascending,\n                             limit: 5\n) { cars in\n  // ...\n}\n```\n\n## 🔑 Authentication Feature Showcase\n\n### Easy User Protocol\n\nSave time writing user classes with the built-in `EasyUser` open class:\n\n```swift\nclass MyUser: EasyUser {\n  \n  // EasyUser comes pre-built with these automatically updated properties\n  var lastSignon: Date\n  var displayName: String\n  var username: String\n  var email: String\n  var appVersion: String\n  var deviceToken: String?\n  var notifications: [MessagingNotification]\n  var disabledMessageCategories: [MessageCategory]\n  var progress: Int\n  var id: String\n  var dateCreated: Date\n  \n  // Define your own custom properties\n  var cars: [Car.ID]\n\n  // ...\n}\n```\n\n⚠️ **Note:** Be sure to read the [the wiki](https://github.com/Flowductive/easy-firebase/wiki/Get-Started-with-EasyAuth) to implement this properly!\n\n### Email Auth\n\nAuthenticate with an email and password easily:\n\n```swift\nEasyAuth.createAccount(email: \"easy.firebase@example.com\", password: \"76dp2[\u0026y4;JLyu:F\") { error in\n  if let error = error {\n    print(error.localizedDescription)\n  } else {\n    // Account created!\n  }\n}\n\nEasyAuth.signIn(email: \"easy.firebase@example.com\", password: \"76dp2[\u0026y4;JLyu:F\") { error in\n  // ...\n}\n```\n\n### Sign In with Google\n\nAuthenticate with Google:\n\n```swift\n// iOS\nEasyAuth.signInWithGoogle(clientID: \"xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\") { error in\n  // ...\n}\n\n// macOS\nEasyAuth.signInWithGoogle(clientID: \"xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n                          secret: \"GOCSPX-xxxxxxxxxxxxxxxxxxx-xxxxxxxx\") { error in\n  // ...\n}\n```\n\n### Sign In with Apple\n\nAuthenticate with Apple:\n\n```swift\n// iOS + macOS\nEasyAuth.signInWithApple()\n```\n\n### Built-In Usernames\n\nGenerate unique usernames and update easily:\n\n```swift\nuser.safelyUpdateUsername(to: \"myNewUsername\", ofUserType: MyUser.self) { error, suggestion in\n if let error = error {\n   // ...\n } else if let suggestion = suggestion {\n   // Username taken, provide the user with an available username suggestion.\n } else {\n   // Success! Username changed.\n }\n}\n```\n\n### Robust User Management\n\nQuickly update and manage `EasyAuth` users:\n\n```swift\n// Send a verfication email to the currently signed-in user\nuser.sendEmailVerification(completion: { error in })\n// Upload and update the current user's profile photo\nuser.updatePhoto(with: myPhotoData, ofUserType: FUser.self, completion: { error in })\n// Send the current user's password reset form to a specified email\nuser.sendPasswordReset(toEmail: \"myResetEmail@example.com\", completion: { error in })\n// Update the current user's display name\nuser.updateDisplayName(to: \"New_DisplayName\", ofUserType: MyUser.self, completion: { error in })\n// Update the current user's password\nuser.updatePassword(to: \"newPassword\", completion: { error in })\n// Delete the current user\nuser.delete(ofUserType: MyUser.self, completion: { error in })\n```\n\n## 📦 Storage Feature Showcase\n\n### Data Storage\n\nQuickly assign data to Firebase Storage using a single line of code.\n\n```swift\n// Upload image data and get an associated URL\nEasyStorage.put(imageData, to: StorageResource(id: user.id)) { url in }\n\n// EasyStorage will automatically delete existing images matching the same ID (if in the same folder)\nEasyStorage.put(imageData,to: StorageResource(id: user.id, folder: \"myFolder\"), progress: { updatedProgress in\n  // Update progress text label using updatedProgress\n}, completion: { url in\n  // Handle the image's URL\n})\n```\n\n## ☁️ Cloud Messaging Feature Showcase\n\n### Built-in User Notifications\n\nEasily send and notify other users without all the tedious setup. Just add a `serverKey` from [Firebase Console](https://console.firebase.google.com).\n\n```swift\n// Set your Server Key\nEasyMessaging.serverKey = \"xxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxx-xxxxx-xxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxx\"\n\n// Create the notification\nlet notification = MessagingNotification(\"Message body\", from: me, in: \"Test Category\")\n\n// Send the notification to the user\n// Appends to the notifications property, unless the specified category is in the user's disabledMessageCategories\nEasyMessaging.send(notification, to: you)\n```\n\n## 📊 Analytics Feature Showcase\n\n### Easily Log Events\n\nTo log an event, you can use `EasyAnalytics`' static methods:\n \n```swift\nEasyAnalytics.log(\"food_eaten\", data: [\n \"name\": \"Hot Dog\",\n \"isHot\": true\n])\n```\n\nIf you have a model that conforms to `AnalyticsLoggable`, you can log events using the model itself:\n\n```swift\nlet hotdog = Food(name: \"Hot Dog\", temperature: 81)\nEasyAnalytics.log(\"food_eaten\", model: hotdog)\n```\n\nAlternatively, you can call the logging method from the model itself:\n\n```swift\nhotdog.log(key: \"food_eaten\")\n```\n\n### Integrated User Properties\n\nOverride the `analyticsProperties()` method to automatically update user properties on app launch:\n\n```swift\nstruct MyUser: EasyUser {\n  // ...\n  var favoriteCar: String\n  func analyticsProperties() -\u003e [String: String] {\n    return [\"app_version\": appVersion, \"favorite_car\": favoriteCar]\n  }\n}\n```\n\nManually update the user properties to Firebase Analytics:\n\n```swift\nmyUser.updateAnalyticsUserProperties()\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFlowductive%2Feasy-firebase","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FFlowductive%2Feasy-firebase","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFlowductive%2Feasy-firebase/lists"}