BackendKit Module Overview
BackendKit is a SwiftyLaunch module that if selected incorporates Firebase Cloud Functions into your app for an easy-to-use backend written in TypeScript.
After generating a project with BackendKit enabled and completing the initial project setup, you will get following features out of the box:
- Server-side code: A set of pre-built backend functions that you can deploy to Firebase Cloud Functions with a single command.
- Client-side code: A set of pre-built client-side functions that you can use to interact with the backend functions.
- Integration with other modules: You can tap into all of SwiftyLaunch modules and their functionality on the backend as well.
Module Deep Dive
Backend Source Code
Once the project is generated, you will see an additional folder next to your Xcode-related files, called Backend. This folder will contain all the code that will end up on in the cloud.
Let's go over some of the most important files and folders in the Backend folder:
.firebaserc
: will contain your Firebase project id. We set it up during the initial project setup.config.ts
: this file will contain all your API keys. We set it up during the initial project setup.src/
: this folder will contain all your backend-related source code. SwiftyLaunch seperates module-specific code into different folders (Such as AnalyticsKit and NotifKit), but the main endpoint backend entry points are defined inindex.ts
. Read how to add a new endpoint here.
Client-Side Code
The client-side code related to backend is shipped as part of the FirebaseKit
module. Out of the box
we define a set of functions that allow you to interact with the backend functions by extending the DB
class. This extension
with an backend usage example can be found in BackendFunctions.swift
.
Here's how a client-side function that fetches all backend users looks like:
extension DB {
public func fetchAllBackendUsers() async -> [FetchedUser] {
do {
// Call the Firebase Cloud Function
let data = try await functions.httpsCallable("fetchAllUsers").call()
// Try to convert the data to an array of dictionaries
guard let usersRaw = data.data as? [[String: Any]] else {
// ... error handling
return []
}
// Then, try to convert the dictionaries to FetchedUser objects
let users = usersRaw.map({ try? FetchedUser(from: $0) })
// Check if all of them are valid
guard let fetchedUsers = users as? [FetchedUser] else {
// ... error handling
return []
}
// ...
// Finally, return the fetched users
return fetchedUsers
} catch {
// ... error handling
return []
}
}
}
The function that it calls, but on the backend, looks like this:
// Define and export "onCall" function
export const fetchAllUsers = onCall(async (request) => {
// ...
try {
const users = await getAuth().listUsers();
let usersArray: FetchedUser[] = [];
users.users.forEach((user) => {
// ...fill usersArray with user data
});
const allDocs = await getFirestore().collection("posts").get();
for (let user of usersArray) {
// ...get all posts of the user
// set the user's post count
user.postsCreated = userPosts.length;
// using InAppPurchaseKit, check if the user has premium and set the userHasPremium property
user.userHasPremium = await InAppPurchases.doesUserHavePremium(
user.userID
);
}
// ...
// Return the users array to the client
return usersArray;
} catch (error) {
// ... error handling
throw new Error("Server Error");
}
});
BackendKit Example View
We also provide a UI that utilizes this and other backend functions in the BackendKit
module depending on the other modules you have selected.
It is located in the BackendFunctionsExampleView.swift
file.
This view:
- Lists all users and tells how many posts they have created (DBKit)
- If you're logged in, displays a "YOU" badge next to your user (AuthKit)
- Shows if the user has premium (InAppPurchaseKit)
- Let's you send a notification to each user (NotifKit)
If you're
encountering this error when trying to run the BackendFunctionsExampleView
example, refer to our
Troubleshooting
section