149 lines
5.3 KiB
Kotlin
149 lines
5.3 KiB
Kotlin
package be.simplenotes.persistence.repositories
|
|
|
|
import be.simplenotes.persistence.*
|
|
import be.simplenotes.persistence.converters.NoteConverter
|
|
import be.simplenotes.persistence.extensions.arrayContains
|
|
import be.simplenotes.types.Note
|
|
import be.simplenotes.types.PersistedNote
|
|
import org.ktorm.database.Database
|
|
import org.ktorm.dsl.*
|
|
import org.ktorm.entity.*
|
|
import java.time.LocalDateTime
|
|
import java.util.*
|
|
import jakarta.inject.Singleton
|
|
|
|
@Singleton
|
|
internal class NoteRepositoryImpl(
|
|
private val db: Database,
|
|
private val converter: NoteConverter,
|
|
) : NoteRepository {
|
|
|
|
override fun findAll(
|
|
userId: Int,
|
|
limit: Int,
|
|
offset: Int,
|
|
tag: String?,
|
|
deleted: Boolean,
|
|
) = db.noteWithTags
|
|
.filterColumns { listOf(it.uuid, it.title, it.updatedAt, it.tags) }
|
|
.filter { (it.userId eq userId) and (it.deleted eq deleted) }
|
|
.runIf(tag != null) { filter { it.tags.arrayContains(tag!!) } }
|
|
.sortedByDescending { it.updatedAt }
|
|
.take(limit)
|
|
.drop(offset)
|
|
.map { converter.toPersistedNoteMetadata(it)!! }
|
|
|
|
override fun exists(userId: Int, uuid: UUID) =
|
|
db.notes.any { (it.userId eq userId) and (it.uuid eq uuid) and (it.deleted eq false) }
|
|
|
|
override fun create(userId: Int, note: Note): PersistedNote = db.useTransaction {
|
|
val uuid = UUID.randomUUID()
|
|
val entity = converter.toEntity(note, uuid, userId, LocalDateTime.now())
|
|
db.notes.add(entity)
|
|
|
|
note.tags.takeIf { it.isNotEmpty() }?.run {
|
|
db.batchInsert(Tags) {
|
|
forEach { tagName ->
|
|
item {
|
|
set(it.noteUuid, uuid)
|
|
set(it.name, tagName)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return find(userId, uuid) ?: error("Note not found")
|
|
}
|
|
|
|
override fun find(userId: Int, uuid: UUID) = db.noteWithTags
|
|
.filterColumns { NotesWithTags.columns - NotesWithTags.userId - NotesWithTags.deleted }
|
|
.find { (it.uuid eq uuid) and (it.userId eq userId) and (it.deleted eq false) }
|
|
.let { converter.toPersistedNote(it) }
|
|
|
|
override fun update(userId: Int, uuid: UUID, note: Note): PersistedNote? = db.useTransaction {
|
|
val now = LocalDateTime.now()
|
|
val count = db.update(Notes) {
|
|
set(it.title, note.title)
|
|
set(it.markdown, note.markdown)
|
|
set(it.html, note.html)
|
|
set(it.updatedAt, now)
|
|
where { (it.uuid eq uuid) and (it.userId eq userId) and (it.deleted eq false) }
|
|
}
|
|
|
|
if (count == 0) return null
|
|
|
|
// delete all tags
|
|
db.delete(Tags) {
|
|
it.noteUuid eq uuid
|
|
}
|
|
|
|
// put new ones
|
|
note.tags.forEach { tagName ->
|
|
db.insert(Tags) {
|
|
set(it.name, tagName)
|
|
set(it.noteUuid, uuid)
|
|
}
|
|
}
|
|
|
|
return find(userId, uuid)
|
|
}
|
|
|
|
override fun delete(userId: Int, uuid: UUID, permanent: Boolean) = if (!permanent) {
|
|
db.update(Notes) {
|
|
set(it.deleted, true)
|
|
set(it.updatedAt, LocalDateTime.now())
|
|
where { it.userId eq userId and (it.uuid eq uuid) }
|
|
} == 1
|
|
} else db.delete(Notes) { it.uuid eq uuid and (it.userId eq userId) } == 1
|
|
|
|
override fun restore(userId: Int, uuid: UUID) = db.update(Notes) {
|
|
set(it.deleted, false)
|
|
where { (it.userId eq userId) and (it.uuid eq uuid) }
|
|
} == 1
|
|
|
|
override fun getTags(userId: Int): List<String> = db.from(Tags)
|
|
.leftJoin(Notes, on = Notes.uuid eq Tags.noteUuid)
|
|
.selectDistinct(Tags.name)
|
|
.where { (Notes.userId eq userId) and (Notes.deleted eq false) }
|
|
.map { it.getString(1)!! }
|
|
|
|
override fun count(userId: Int, tag: String?, deleted: Boolean) = db.from(Notes)
|
|
.runIf(tag != null) { leftJoin(Tags, on = Tags.noteUuid eq Notes.uuid) }
|
|
.select(count())
|
|
.whereWithConditions {
|
|
it += Notes.userId eq userId
|
|
it += Notes.deleted eq deleted
|
|
tag?.let { tag -> it += Tags.name eq tag }
|
|
}
|
|
.map { it.getInt(1) }
|
|
.first()
|
|
|
|
override fun export(userId: Int) = db.noteWithTags
|
|
.filterColumns { it.columns - it.userId - it.public }
|
|
.filter { it.userId eq userId }
|
|
.sortedByDescending { it.updatedAt }
|
|
.map { converter.toExportedNote(it)!! }
|
|
|
|
override fun findAllDetails(userId: Int) = db.noteWithTags
|
|
.filterColumns { it.columns - it.userId - it.deleted }
|
|
.filter { (it.userId eq userId) and (it.deleted eq false) }
|
|
.map { converter.toPersistedNote(it)!! }
|
|
|
|
override fun makePublic(userId: Int, uuid: UUID) = db.update(Notes) {
|
|
set(it.public, true)
|
|
where { Notes.userId eq userId and (Notes.uuid eq uuid) and (it.deleted eq false) }
|
|
} == 1
|
|
|
|
override fun makePrivate(userId: Int, uuid: UUID) = db.update(Notes) {
|
|
set(it.public, false)
|
|
where { Notes.userId eq userId and (Notes.uuid eq uuid) and (it.deleted eq false) }
|
|
} == 1
|
|
|
|
override fun findPublic(uuid: UUID) = db.noteWithTags
|
|
.filterColumns { it.columns - it.userId - it.deleted }
|
|
.find { (it.uuid eq uuid) and (it.public eq true) and (it.deleted eq false) }
|
|
.let { converter.toPersistedNote(it) }
|
|
}
|
|
|
|
private inline fun <T> T.runIf(condition: Boolean, block: T.() -> T) = run { if (condition) block(this) else this }
|