GithubHelp home page GithubHelp logo

flowductive / easy-firebase Goto Github PK

View Code? Open in Web Editor NEW
73.0 3.0 7.0 83.86 MB

๐Ÿ”ฅ A Swifty solution for all things Firebase. Quickly implement Firestore and Authentication on iOS + macOS using Swift protocols and methods.

License: MIT License

Swift 100.00%
firebase firestore swift ios macos authentication signinwithgoogle firebase-auth sign-in-with-apple sign-in-with-google

easy-firebase's Introduction

Social Preview

Firebase for iOS and macOS made easy.

๐Ÿ Third-party authentication done in a single line of code

โœ‰๏ธ Send and receive Firestore documents in a snap

๐Ÿ˜€ Predefined user protocols with built-in features

๐Ÿ”ฅ Firebase solutions in one native Swift package

๐Ÿ“˜ Fully documented code with examples


โš ๏ธ Note: This package is still under development and its contents are freely subject to change.

๐Ÿ“š Ready to get started? Check out our complete wiki for detailed guides.

GitHub release (latest SemVer) GitHub Release Date GitHub issues GitHub pull requests

What is EasyFirebase?

EasyFirebase 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.

Completed Features

  • Firestore Support
  • Authentication Support
  • Storage Support
    • Data storage โ†’
    • Safe data overriding
    • Data removal
    • Data upload task visibility
  • Cloud Messaging Support
    • Built-in user notifications โ†’
    • Built-in MessagingNotification protocol
    • Built-in 3P notifications
    • User notification settings
  • Analytics Support

All the above features are cross-platform and are supported on both iOS and macOS.

โญ๏ธ This means EasyFirebase is the quickest way to implement Sign In with Google on macOS! โญ๏ธ

Get Started

Add EasyFirebase to your project using Swift Package Manager:

https://github.com/Flowductive/easy-firebase

Import EasyFirebase:

import EasyFirebase

Configure at app launch:

// You don't need to call FirebaseApp.configure() when this is called!
EasyFirebase.configure()

๐Ÿ”ฅ Firestore Feature Showcase

Built-in Document protocol

Save time writing model classes with the built-in Document protocol:

class Car: Document {
  
  // These properties are inherited from Document
  var id: String = UUID().uuidString
  var dateCreated: Date = Date()
  
  // Define your own custom properties
  var make: String
  var model: String
  var year: Int
  
  init(make: String, model: String, year: Int) {
    // ...
  }
}

Document Storage

Store documents anywhere in your code:

var myCar = Car(make: "Toyota", model: "Corolla", year: 2017)

// Store the car instance in the 'car' collection in Firestore
myCar.set()

// Static method that does the same as above
EasyFirestore.Storage.set(myCar)

Document Retrieval

Grab documents easily without needing to specify a collection name:

EasyFirestore.Retrieval.get(id: myCarID, ofType: Car.self) { car in
  guard let car = car else { return }
  self.myOtherCar = car
}

Document Updating

Update fields remotely in Firestore without performing any reads.

// Append element to array
EasyFirestore.Updating.append(\.ingredients, with: "Cheese", in: pizzaDocument) { error in ... }

// Increment field
EasyFirestore.Updating.increment(\.pepperoniCount, by: 5, in: pizzaDocument)

// Remove elements from array
EasyFirestore.Updating.remove(\.ingredients, taking: ["Garlic", "Anchovies", "Pineapple"], from: pizzaDocument)

Update Listeners

Grab documents and update the local instance when changed in Firestore:

EasyFirestore.Listening.listen(to: otherCarID, ofType: Car.self, key: "myCarListenerKey") { car in
  // Updates when changed in Firestore
  guard let car = car else { return }
  self.myOtherCar = car
}

Built-In Cacheing

EasyFirestore will automatically cache fetched documents locally and will use the cached doucments when retrieving to reduce your Firestore read count.

// EasyFirebase will automatically cache fetched objects for you, here is a manual example
EasyFirestore.Cacheing.register(myCar)

// Get locally cached objects instantly. Retrieving objects using EasyFirestore.Retrieval will grab cached objects if they exist
var cachedCar = EasyFirestore.Cacheing.grab(myCarID, fromType: Car.self)

Easy Linking

Link child documents to an array of IDs in a parent document:

var car1 = Car(make: "Toyota", model: "Corolla", year: 2017)
var car2 = Car(make: "Honda", model: "Civic", year: 2019)

var dealership = Dealership(name: "Los Angeles Dealership")

// Set and assign the Toyota Corolla to the Los Angeles Dealership
car1.setAssign(toField: "cars", using: \.cars, in: dealership)

// Set and assign the Honda Civic to the Los Angeles Dealership
car2.set()
car2.assign(toField: "cars", using: \.cars, in: dealership)

Swifty Querying

Easily query for documents:

EasyFirestore.Querying.where(\Car.make, .equals, "Toyota") { cars in
  // Handle your queried documents here...
}

Use multiple conditions for queries; order and limit results:

EasyFirestore.Querying.where((\Car.year, .greaterEqualTo, 2010),
                             (\Car.model, .in, ["Corolla", "Camry"]),
                             order: .ascending,
                             limit: 5
) { cars in
  // ...
}

๐Ÿ”‘ Authentication Feature Showcase

Easy User Protocol

Save time writing user classes with the built-in EasyUser open class:

class MyUser: EasyUser {
  
  // EasyUser comes pre-built with these automatically updated properties
  var lastSignon: Date
  var displayName: String
  var username: String
  var email: String
  var appVersion: String
  var deviceToken: String?
  var notifications: [MessagingNotification]
  var disabledMessageCategories: [MessageCategory]
  var progress: Int
  var id: String
  var dateCreated: Date
  
  // Define your own custom properties
  var cars: [Car.ID]

  // ...
}

โš ๏ธ Note: Be sure to read the the wiki to implement this properly!

Email Auth

Authenticate with an email and password easily:

EasyAuth.createAccount(email: "[email protected]", password: "76dp2[&y4;JLyu:F") { error in
  if let error = error {
    print(error.localizedDescription)
  } else {
    // Account created!
  }
}

EasyAuth.signIn(email: "[email protected]", password: "76dp2[&y4;JLyu:F") { error in
  // ...
}

Sign In with Google

Authenticate with Google:

// iOS
EasyAuth.signInWithGoogle(clientID: "xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") { error in
  // ...
}

// macOS
EasyAuth.signInWithGoogle(clientID: "xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                          secret: "GOCSPX-xxxxxxxxxxxxxxxxxxx-xxxxxxxx") { error in
  // ...
}

Sign In with Apple

Authenticate with Apple:

// iOS + macOS
EasyAuth.signInWithApple()

Built-In Usernames

Generate unique usernames and update easily:

user.safelyUpdateUsername(to: "myNewUsername", ofUserType: MyUser.self) { error, suggestion in
 if let error = error {
   // ...
 } else if let suggestion = suggestion {
   // Username taken, provide the user with an available username suggestion.
 } else {
   // Success! Username changed.
 }
}

Robust User Management

Quickly update and manage EasyAuth users:

// Send a verfication email to the currently signed-in user
user.sendEmailVerification(completion: { error in })
// Upload and update the current user's profile photo
user.updatePhoto(with: myPhotoData, ofUserType: FUser.self, completion: { error in })
// Send the current user's password reset form to a specified email
user.sendPasswordReset(toEmail: "[email protected]", completion: { error in })
// Update the current user's display name
user.updateDisplayName(to: "New_DisplayName", ofUserType: MyUser.self, completion: { error in })
// Update the current user's password
user.updatePassword(to: "newPassword", completion: { error in })
// Delete the current user
user.delete(ofUserType: MyUser.self, completion: { error in })

๐Ÿ“ฆ Storage Feature Showcase

Data Storage

Quickly assign data to Firebase Storage using a single line of code.

// Upload image data and get an associated URL
EasyStorage.put(imageData, to: StorageResource(id: user.id)) { url in }

// EasyStorage will automatically delete existing images matching the same ID (if in the same folder)
EasyStorage.put(imageData,to: StorageResource(id: user.id, folder: "myFolder"), progress: { updatedProgress in
  // Update progress text label using updatedProgress
}, completion: { url in
  // Handle the image's URL
})

โ˜๏ธ Cloud Messaging Feature Showcase

Built-in User Notifications

Easily send and notify other users without all the tedious setup. Just add a serverKey from Firebase Console.

// Set your Server Key
EasyMessaging.serverKey = "xxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxx-xxxxx-xxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxx"

// Create the notification
let notification = MessagingNotification("Message body", from: me, in: "Test Category")

// Send the notification to the user
// Appends to the notifications property, unless the specified category is in the user's disabledMessageCategories
EasyMessaging.send(notification, to: you)

๐Ÿ“Š Analytics Feature Showcase

Easily Log Events

To log an event, you can use EasyAnalytics' static methods:

EasyAnalytics.log("food_eaten", data: [
 "name": "Hot Dog",
 "isHot": true
])

If you have a model that conforms to AnalyticsLoggable, you can log events using the model itself:

let hotdog = Food(name: "Hot Dog", temperature: 81)
EasyAnalytics.log("food_eaten", model: hotdog)

Alternatively, you can call the logging method from the model itself:

hotdog.log(key: "food_eaten")

Integrated User Properties

Override the analyticsProperties() method to automatically update user properties on app launch:

struct MyUser: EasyUser {
  // ...
  var favoriteCar: String
  func analyticsProperties() -> [String: String] {
    return ["app_version": appVersion, "favorite_car": favoriteCar]
  }
}

Manually update the user properties to Firebase Analytics:

myUser.updateAnalyticsUserProperties()

easy-firebase's People

Contributors

benlmyers avatar internetdhruv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

easy-firebase's Issues

v2.0 does not build

Build fails because EasyUser was restricted to iOS13+, but CloudMessaging and other consumers were not given this restriction

Proposed fix: #1

Eliminate Static Methods

Remove all need for static library methods like EasyFirestore.Updating.increment(...) or EasyStorage.put(...) by translating all related methods to Document and other related classes/objects.

Remove `ofType:` and `userType:` parameters in method calls

The need for ofType: and userType: to specialize generic EasyFirestore and other related library methods can be eliminated, as String(describing: T.self) does not account for sub-classes, whereas String(describing: type(of: document)).

This change should only appear rarely, however, once #9 is implemented.

Cocoapod

Do you have any idea for support cocoapod?

IOS EasyAuth.signOut() does not sign out.

Love the design of your library, though I'm having a few issues with EasyAuth.

I've been attempting to use easy-firebase for a basic email authentication IOS app, and it seems there there are some issues in the IOS example that are also happening when I implement the library with the base instructions provided.

Reproducible by compiling the latest IOS example, signing in with email, and attempting to sign out.

IOS 16.2
Iphone 14 Pro
easy-firebase 1.4.3

Firestore rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

After setting the state of my app to "signed out", which brings my app back to it's original Sign In form, and running "EasyAuth.signOut()", I receive the following logged errors:

Screenshot 2023-03-06 at 12 33 32 PM

This is not a problem if I change my firestore rules to just "allow read, write;" (which is certainly not a solution). Is there a listener that could still be attached when the sign out function succeeds and my auth header is no longer valid?

Widening Queries

Allow queries to "widen" if a Firestore query returns no results.

Dynamic Collection + Subcollection Support

Support for any name of collection or sub collection. Proposed solution: enumeration states holding references to specific collections, sub-collections, or documents.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.