Backend as an implementation detail

AppKickstarter is designed with a high level of abstraction for core functionalities such as Authentication, Remote Data Storage, and Remote Document Storage. This architectural choice ensures flexibility, allowing for easy substitution of Firebase or any other backend services. This section guides you through customizing the endpoints for Authentication, Storage, and Database services by leveraging the power of dependency injection with Koin.

Create a Koin module

To begin customizing your backend services, create a Koin module that will hold your implementations:

val customRemoteModule = module {
    // your implementations, see below
}

Storage

To customize storage solutions, implement the IRemoteFileSystem interface:

interface IRemoteFileSystem {
    suspend fun putFileAt(localFile: LocalFile, location: String): FileUrl
}

Then, register your custom storage implementation in the Koin module:

singleOf(::CustomRemoteFileSystemImpl) bind IRemoteFileSystem::class

Database

For custom database interactions, implement the IUserRemoteDB interface:

interface IUserRemoteDB { 
    suspend fun getUserInfos(userId: String): User? 
    suspend fun postUserInfos(user: User) 
}

And add your implementation to the Koin module for dependency injection:

singleOf(::CustomUserRemoteImpl) bind IUserRemoteDB::class

Posts Management

AppKickstarter includes default data manipulation examples, such as creating user posts with text, date, and images, and displaying them in a feed. To integrate a custom solution for posts storage:

Implement the IPostsRemoteDB interface:

interface IPostsRemoteDB { 
    suspend fun uploadPost(post: Post): String 
    suspend fun getAllPosts(): List 
    suspend fun deletePost(id: String)
}

Register your implementation in the Koin module:

singleOf(::CustomPostsRemoteImpl) bind IPostsRemoteDB::class

Authentication

To customize authentication mechanisms, implement the KickstarterAuth interface:

interface KickstarterAuth {
    suspend fun signout()
    fun getCurrentUser(): CurrentUser?
    fun observeAuthStateChanged(): Flow<CurrentUser?>
    suspend fun observeSessionStatus(): Flow<SessionStatus>
    suspend fun signInAnonymously(): CurrentUser?
    suspend fun resetPassword(email: String)
    suspend fun createUserWithEmailAndPassword(email: String, password: String): CurrentUser?
    suspend fun signInWithEmailAndPassword(email: String, password: String): CurrentUser?
}

Finally, integrate your custom authentication service into the Koin module:

singleOf(::CustomRemoteAuth) bind KickstarterAuth::class

Wrap it up

To finalize the customization of your backend services in AppKickstarter, ensure your customRemoteModule is defined as follows:

val customRemoteModule = module {
    singleOf(::CustomemoteFileSystemImpl) bind IRemoteFileSystem::class
    singleOf(::CustomUserRemoteImpl) bind IUserRemoteDB::class
    singleOf(::CustomPostsRemoteImpl) bind IPostsRemoteDB::class
    singleOf(::CustomRemoteAuth) bind KickstarterAuth::class
}

Navigate to shared/commonMain/sharedModule/initKoin, and make the following adjustments:

  1. Remove the firebaseModule: This step is crucial as it disconnects the default Firebase implementations from your app's dependency graph.

  2. Add customRemoteModule: By adding your custom module, you effectively replace the default services with your tailored implementations.

By completing these steps, you have successfully set up custom endpoints for Authentication, Storage, and Database services in AppKickstarter. This approach ensures that the core functionalities of your app are not tightly coupled with Firebase or any specific backend service.

Last updated