package be.simplenotes.app import be.simplenotes.app.api.ApiNoteController import be.simplenotes.app.api.ApiUserController import be.simplenotes.app.controllers.BaseController import be.simplenotes.app.controllers.NoteController import be.simplenotes.app.controllers.SettingsController import be.simplenotes.app.controllers.UserController import be.simplenotes.app.filters.AuthFilter import be.simplenotes.app.filters.AuthType import be.simplenotes.app.filters.ErrorFilter import be.simplenotes.app.filters.JwtSource import be.simplenotes.app.routes.Router import be.simplenotes.app.utils.StaticFileResolver import be.simplenotes.app.utils.StaticFileResolverImpl import be.simplenotes.app.views.* import be.simplenotes.domain.domainModule import be.simplenotes.domain.usecases.NoteService import be.simplenotes.persistance.DbMigrations import be.simplenotes.persistance.persistanceModule import be.simplenotes.search.searchModule import be.simplenotes.shared.config.DataSourceConfig import be.simplenotes.shared.config.JwtConfig import kotlinx.serialization.KSerializer import kotlinx.serialization.descriptors.PrimitiveKind import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.Json import kotlinx.serialization.modules.SerializersModule import org.http4k.core.RequestContexts import org.koin.core.context.startKoin import org.koin.core.qualifier.named import org.koin.core.qualifier.qualifier import org.koin.dsl.module import org.slf4j.LoggerFactory import java.time.LocalDateTime import java.util.* import be.simplenotes.shared.config.ServerConfig as SimpleNotesServeConfig fun main() { val koin = startKoin { modules( persistanceModule, configModule, domainModule, serverModule, userModule, baseModule, noteModule, settingsModule, searchModule, apiModule, ) }.koin val dataSourceConfig = koin.get() val jwtConfig = koin.get() val serverConfig = koin.get() val logger = LoggerFactory.getLogger("SimpleNotes") logger.info("datasource: $dataSourceConfig") logger.info("jwt: $jwtConfig") logger.info("server: $serverConfig") val migrations = koin.get() migrations.migrate() val noteService = koin.get() noteService.dropAllIndexes() noteService.indexAll() koin.get().start() } val serverModule = module { single { Server(get(), get(), get()) } single { StaticFileResolverImpl() } single { Router( get(), get(), get(), get(), get(), get(), requiredAuth = get(AuthType.Required.qualifier), optionalAuth = get(AuthType.Optional.qualifier), errorFilter = get(named("ErrorFilter")), apiAuth = get(named("apiAuthFilter")), get() )() } single { serverConfig(get()) } single { RequestContexts() } single(AuthType.Optional.qualifier) { AuthFilter(get(), AuthType.Optional, get())() } single(AuthType.Required.qualifier) { AuthFilter(get(), AuthType.Required, get())() } single(named("ErrorFilter")) { ErrorFilter(get())() } single { ErrorView(get()) } } val userModule = module { single { UserController(get(), get(), get()) } single { UserView(get()) } } val baseModule = module { single { BaseController(get()) } single { BaseView(get()) } } val noteModule = module { single { NoteController(get(), get()) } single { NoteView(get()) } } val settingsModule = module { single { SettingsController(get(), get()) } single { SettingView(get()) } } val configModule = module { single { Config.dataSourceConfig } single { Config.jwtConfig } single { Config.serverConfig } } val apiModule = module { single { ApiUserController(get(), get()) } single { ApiNoteController(get(), get()) } single { Json { prettyPrint = true serializersModule = get() } } single { SerializersModule { contextual(LocalDateTime::class, LocalDateTimeSerializer) contextual(UUID::class, UuidSerializer) } } single(named("apiAuthFilter")) { AuthFilter( extractor = get(), authType = AuthType.Required, ctx = get(), source = JwtSource.Header, redirect = false )() } } internal object LocalDateTimeSerializer : KSerializer { override val descriptor: SerialDescriptor get() = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: LocalDateTime) { encoder.encodeString(value.toString()) } override fun deserialize(decoder: Decoder): LocalDateTime { TODO("Not implemented, isn't needed") } } internal object UuidSerializer : KSerializer { override val descriptor: SerialDescriptor get() = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: UUID) { encoder.encodeString(value.toString()) } override fun deserialize(decoder: Decoder): UUID { TODO() } }