- Notifications
You must be signed in to change notification settings - Fork12
Vapor Firebase Realtime database provider
License
vapor-community/ferno
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Ferno allows you to easily connect your Vapor project with your Firebase realtime database. It is built with the brand new Vapor 4. It gives you a nice and clean interface to interact with the Firebase Realtime REST API. It will automatically turn the response into your class/struct!
You will need:
- Vapor 4.8+
In your Package.swift file, add the line
.package(url:"https://github.com/vapor-community/ferno.git", from:"0.6.0")
Also make sure you addFerno
as a dependency
dependencies:[.product(name:"Ferno",package:"ferno")]
Ferno uses an access token to read and write to your database. First we will need to get your service account information.
- Log into the Firebase console
- Click the settings gear next to
Project Overview
- Select
Project settings
- Select the
SERVICE ACCOUNTS
tab - Click the button at the bottom that says
GENERATE NEW PRIVATE KEY
- This will download a
.json
file. You will now have access to the email and private key. You will pass those into the initialize during the next step.
Register
Ferno
as a Provider and importFerno
. This is usually done inconfigure.swift
- Log into the Firebase console
- Click the settings gear next to
Project Overview
- Select
Project settings
- Select the
SERVICE ACCOUNTS
tab - Select
Firebase Admin SDK
option - Click the button
Generate new private key
to download the json file.
You can use the content of json file information to fill out theFernoDefaultConfiguration
or use the json file to preper theFernoServiceJsonConfiguration
.
import FernoletfernoConfiguration=FernoDefaultConfiguration( basePath:"database-url", email:"service-account-email", privateKey:"private-key")app.ferno.use(.default(fernoConfiguration))
If you prefer to use the FirebaseServiceAccount.json
follow the example below.
import Ferno// option 1letfernoConfiguration=tryFernoServiceJsonConfiguration(json: Data)// option 2letfernoConfiguration=tryFernoServiceJsonConfiguration(path: URL)// option 3letfernoConfiguration=FernoServiceJsonConfiguration( type: String, projectId: String, privateKeyId: String, privateKey: String, clientEmail: String, clientId: String, authUri: String, tokenUri: String, authProviderX509CertUrl: String, clientX509CertUrl: String, universeDomain: String)app.ferno.use(.serviceAccountKey(fernoConfiguration))
There are some custom parameters to pass into functions. I want to go over all the parameters you will need to know.
In GET requests, you might want to query on your data. This is what[FernoQuery]
is for.
FernoQuery
is an enum with:
case shallow(Bool)
case orderBy(FernoValue)
case limitToFirst(FernoValue)
case limitToLast(FernoValue)
case startAt(FernoValue)
case endAt(FernoValue)
case equalTo(FernoValue)
These are all the possible queries that are allowed on Firebase according to thedocs
shallow(Bool)
cannot be mixed with any other query parameters.- you usually use
orderBy(FernoValue)
in conjunction with enums3-7
- using
orderBy(FernoValue)
alone will just order the data returned
You will notice most cases inFernoQuery
have a value ofFernoValue
.FernoValue
is just a wrapper forBool, String, Int, Double, Float
. So you can just do.startAt(5)
and everything will work.
Just using shallow:
[.shallow(true)]
Filter data to only return data that matches"age": 21
:
[.orderBy("age"),.equalTo(21)]
Just orderBy(returns data in ascending order):
[.orderBy("age")]
There are 6 functions that allow you to interact with your Firebase realtime database.
There are four functions that allow you get your data.
app.ferno.retrieve(_ path:[String], queryItems:[FernoQuery]=[])
app.ferno.retrieve(_ path: String..., queryItems:[FernoQuery]=[])
app.ferno.retrieveMany(_ path:[String], queryItems:[FernoQuery]=[])
app.ferno.retrieveMany(_ path: String..., queryItems:[FernoQuery]=[])
The only difference betweenretrieve
andretrieveMany
is the return type.
retrieve
returns ->F
whereF
is of typeDecodable
retrieveMany
returns ->[String: F]
whereF
is of typeDecodable
andString
is the key
- Define the value you want the data converted.
structDeveloper:Content{varname:StringvarfavLanguage:Stringvarage:Int}
- Make the request. Make sure you set the type of the response so Ferno knows what to convert.
letdevelopers:[String:Developer]=tryawait app.ferno.retrieveMany("developers")letdeveloper:Developer=tryawait app.ferno.retrieve(["developers","dev1"])
Used to create a new entry in your database
app.ferno.create(_ path:[String], body: T)tryawait-> FernoChild
app.ferno.create(_ path: String..., body: T)tryawait-> FernoChild
body: T
is of typeContent
.FernoChild
is a struct:
structFernoChild:Content{varname:String}
FernoChild
is returned, because the API request returns the key from the newly created child.
letnewDeveloper=Developer(name:"Elon", favLanguage:"Python", age:46) // conforms to ContentletnewDeveloperKey:FernoChild=tryawait app.ferno.create("developers", body: newDeveloper)
Used to delete an entry in your database
app.ferno.delete(_ path:[String])tryawait-> Bool
app.ferno.delete(_ path: String...)tryawait-> Bool
- the delete method will return a boolean depending on if the delete was successful
letsuccessfulDelete:Bool=tryawait app.ferno.delete(["developers","dev-1"])
Update values at a specific location, but omitted values won't get removed
app.ferno.update(_ path:[String], body: T)tryawait-> T
app.ferno.update(_ path: String..., body: T)tryawait-> T
- the update method will return the body
structUpdateDeveloperName:Content{varname:String}letnewDeveloperName=UpdateDeveloperName(name:"Kimbal") //conforms to ContentletupdatedDeveloperName:UpdateDeveloperName=tryawait app.ferno.update(["developers", newDeveloperKey.name], body: newDeveloper) //newDeveloperKey.name comes from the create method
Overwrite the current location with data you are passing in
client.ferno.overwrite(_ path:[String], body: T)tryawait-> T
client.ferno.overwrite(_ path: String..., body: T)tryawait-> T
structLeadDeveloper:Content{varname:Stringvarcompany:Stringvarage:Int}letleadDeveloper=LeadDeveloper(name:"Ashley", company:"Bio-Fit", age:20)letleadDevResponse:LeadDeveloper=tryawait app.ferno.overwrite(["developers", newDeveloperKey.name], body: leadDeveloper)
Currently, tests were written using an actual dummy Firebase realtime database. If you want to run all of the tests, you will need to create a dummy Firebase realtime database.
You need to go toApplication+Testing.swift
and fill in the missing values based on your Firebase service account. Then you will be able to run tests.
- Austin Astorga -Main developer
- Maxim Krouk -Migration to Vapor4
- Petr Pavlik -Migrated to async/await
This project is licensed under the MIT License - see theLICENSE.md file for details
- Vapor Discord (for helping me with all my issues <3)
- Stripe Provider as a great template!stripe-provider
About
Vapor Firebase Realtime database provider