full reborn
This commit is contained in:
.github/workflows
LICENSEREADME.mdbuild.gradlebusiness_cases/post_creating
client
common
src
commonMain
kotlin
dev
inmo
postssystem
business_cases
post_creating
main
server
client
build.gradle
src
commonMain
kotlin
dev
inmo
jsMain
kotlin
dev
resources
jvmMain
kotlin
dev
inmo
postssystem
client
main
core
api
src
commonMain
kotlin
dev
inmo
postssystem
core
commonTest
kotlin
dev
inmo
postssystem
core
jvmMain
kotlin
dev
inmo
postssystem
core
content
api
business
content_adapters
binary
main
exposed
build.gradlegradle.properties
src
jvmMain
kotlin
dev
inmo
postssystem
core
exposed
jvmTest
kotlin
dev
inmo
postssystem
ktor
client
common
src
commonMain
kotlin
dev
inmo
postssystem
main
server
features
auth
client
common
server
common
client
common
build.gradle
src
commonMain
kotlin
dev
inmo
postssystem
features
common
jvmMain
kotlin
dev
inmo
postssystem
features
common
common
main
server
files
client
build.gradle
src
common
build.gradle
src
commonMain
kotlin
dev
inmo
postssystem
features
jvmMain
kotlin
dev
inmo
postssystem
features
main
server
roles
client
common
manager
client
common
server
server
status
template
client
common
server
users
client
common
build.gradle
src
commonMain
kotlin
dev
inmo
postssystem
features
users
jvmMain
kotlin
dev
inmo
postssystem
features
users
common
main
server
gradle/wrapper
gradlewgradlew.batmimes_generator
mppAndroidProject.gradlemppJavaProject.gradlemppJsProject.gradlemppProjectWithSerialization.gradlepubconf.kpsbpublish.gradlepublish.kpsbpublishing
api
src
commonMain
kotlin
main
exposed
ktor
client
src
commonMain
kotlin
com
insanusmokrassar
postssystem
main
common
src
commonMain
kotlin
com
insanusmokrassar
main
server
server
settings.gradle
6
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/Constants.kt
Normal file
6
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/Constants.kt
Normal file
@@ -0,0 +1,6 @@
|
||||
package dev.inmo.postssystem.features.files.common
|
||||
|
||||
const val filesRootPathPart = "files"
|
||||
const val filesGetFilesPathPart = "getFiles"
|
||||
const val filesGetFullFileInfoPathPart = "getFullFileInfo"
|
||||
const val filesFileIdParameter = "fileId"
|
35
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/FileInfo.kt
Normal file
35
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/FileInfo.kt
Normal file
@@ -0,0 +1,35 @@
|
||||
package dev.inmo.postssystem.features.files.common
|
||||
|
||||
import dev.inmo.micro_utils.common.*
|
||||
import dev.inmo.micro_utils.mime_types.MimeType
|
||||
import dev.inmo.micro_utils.serialization.typed_serializer.TypedSerializer
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable(FileInfoSerializer::class)
|
||||
sealed interface FileInfo {
|
||||
val name: FileName
|
||||
val mimeType: MimeType
|
||||
|
||||
companion object {
|
||||
fun serializer(): KSerializer<FileInfo> = FileInfoSerializer
|
||||
}
|
||||
}
|
||||
|
||||
object FileInfoSerializer : KSerializer<FileInfo> by TypedSerializer(
|
||||
"meta" to MetaFileInfo.serializer(),
|
||||
"full" to FullFileInfo.serializer(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MetaFileInfo(override val name: FileName, override val mimeType: MimeType) : FileInfo
|
||||
|
||||
@Serializable
|
||||
data class FullFileInfo(
|
||||
override val name: FileName,
|
||||
override val mimeType: MimeType,
|
||||
@Serializable(ByteArrayAllocatorSerializer::class)
|
||||
val byteArrayAllocator: ByteArrayAllocator
|
||||
) : FileInfo
|
||||
|
||||
fun FullFileInfo.toMetaFileInfo() = MetaFileInfo(name, mimeType)
|
21
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/FileInfoWrapper.kt
Normal file
21
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/FileInfoWrapper.kt
Normal file
@@ -0,0 +1,21 @@
|
||||
package dev.inmo.postssystem.features.files.common
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlin.jvm.JvmInline
|
||||
|
||||
|
||||
@Serializable
|
||||
@JvmInline
|
||||
value class FileId(val string: String) {
|
||||
override fun toString(): String = string.toString()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
sealed class FileInfoStorageWrapper {
|
||||
abstract val id: FileId
|
||||
abstract val fileInfo: FileInfo
|
||||
}
|
||||
@Serializable
|
||||
data class MetaFileInfoStorageWrapper(override val id: FileId, override val fileInfo: MetaFileInfo) : FileInfoStorageWrapper()
|
||||
@Serializable
|
||||
data class FullFileInfoStorageWrapper(override val id: FileId, override val fileInfo: FullFileInfo) : FileInfoStorageWrapper()
|
9
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FilesStorage.kt
Normal file
9
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FilesStorage.kt
Normal file
@@ -0,0 +1,9 @@
|
||||
package dev.inmo.postssystem.features.files.common.storage
|
||||
|
||||
import dev.inmo.postssystem.features.files.common.*
|
||||
import dev.inmo.micro_utils.repos.ReadCRUDRepo
|
||||
|
||||
interface FilesStorage : ReadCRUDRepo<MetaFileInfoStorageWrapper, FileId> {
|
||||
suspend fun getBytes(id: FileId): ByteArray
|
||||
suspend fun getFullFileInfo(id: FileId): FullFileInfoStorageWrapper?
|
||||
}
|
8
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FullFilesStorage.kt
Normal file
8
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/FullFilesStorage.kt
Normal file
@@ -0,0 +1,8 @@
|
||||
package dev.inmo.postssystem.features.files.common.storage
|
||||
|
||||
interface FullFilesStorage : FilesStorage, WriteFilesStorage
|
||||
|
||||
class DefaultFullFilesStorage(
|
||||
filesStorage: FilesStorage,
|
||||
writeFilesStorage: WriteFilesStorage
|
||||
) : FullFilesStorage, FilesStorage by filesStorage, WriteFilesStorage by writeFilesStorage
|
6
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/WriteFilesStorage.kt
Normal file
6
features/files/common/src/commonMain/kotlin/dev/inmo/postssystem/features/files/common/storage/WriteFilesStorage.kt
Normal file
@@ -0,0 +1,6 @@
|
||||
package dev.inmo.postssystem.features.files.common.storage
|
||||
|
||||
import dev.inmo.postssystem.features.files.common.*
|
||||
import dev.inmo.micro_utils.repos.WriteCRUDRepo
|
||||
|
||||
interface WriteFilesStorage : WriteCRUDRepo<FullFileInfoStorageWrapper, FileId, FullFileInfo>
|
63
features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/DiskFilesStorage.kt
Normal file
63
features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/DiskFilesStorage.kt
Normal file
@@ -0,0 +1,63 @@
|
||||
package dev.inmo.postssystem.features.files.common
|
||||
|
||||
import dev.inmo.postssystem.features.files.common.storage.FilesStorage
|
||||
import dev.inmo.micro_utils.pagination.*
|
||||
import dev.inmo.micro_utils.repos.ReadKeyValueRepo
|
||||
import java.io.File
|
||||
|
||||
class DiskFilesStorage(
|
||||
private val filesFolder: File,
|
||||
private val metasKeyValueRepo: ReadKeyValueRepo<FileId, MetaFileInfo>
|
||||
) : FilesStorage {
|
||||
private val FileId.file
|
||||
get() = File(filesFolder, string)
|
||||
|
||||
init {
|
||||
if (!filesFolder.exists()) {
|
||||
filesFolder.mkdirs()
|
||||
} else {
|
||||
require(filesFolder.isDirectory) { "$filesFolder must be a directory" }
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun FileId.meta(): MetaFileInfoStorageWrapper? {
|
||||
return MetaFileInfoStorageWrapper(
|
||||
this,
|
||||
metasKeyValueRepo.get(this) ?: return null
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getBytes(id: FileId): ByteArray = id.file.readBytes()
|
||||
|
||||
override suspend fun getFullFileInfo(id: FileId): FullFileInfoStorageWrapper? = getById(
|
||||
id
|
||||
) ?.let {
|
||||
FullFileInfoStorageWrapper(
|
||||
id,
|
||||
FullFileInfo(
|
||||
it.fileInfo.name,
|
||||
it.fileInfo.mimeType
|
||||
) {
|
||||
id.file.readBytes()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun contains(id: FileId): Boolean = metasKeyValueRepo.contains(id)
|
||||
|
||||
override suspend fun count(): Long = metasKeyValueRepo.count()
|
||||
|
||||
override suspend fun getById(id: FileId): MetaFileInfoStorageWrapper? = id.meta()
|
||||
|
||||
override suspend fun getByPagination(pagination: Pagination): PaginationResult<MetaFileInfoStorageWrapper> {
|
||||
val keys = metasKeyValueRepo.keys(pagination)
|
||||
return keys.changeResults(
|
||||
keys.results.mapNotNull {
|
||||
MetaFileInfoStorageWrapper(
|
||||
it,
|
||||
metasKeyValueRepo.get(it) ?: return@mapNotNull null
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
15
features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/MetasKeyValueRepo.kt
Normal file
15
features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/MetasKeyValueRepo.kt
Normal file
@@ -0,0 +1,15 @@
|
||||
package dev.inmo.postssystem.features.files.common
|
||||
|
||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.mappers.withMapper
|
||||
import kotlinx.serialization.StringFormat
|
||||
|
||||
fun MetasKeyValueRepo(
|
||||
serialFormat: StringFormat,
|
||||
originalRepo: KeyValueRepo<String, String>
|
||||
) = originalRepo.withMapper<FileId, MetaFileInfo, String, String>(
|
||||
{ string },
|
||||
{ serialFormat.encodeToString(MetaFileInfo.serializer(), this) },
|
||||
{ FileId(this) },
|
||||
{ serialFormat.decodeFromString(MetaFileInfo.serializer(), this) }
|
||||
)
|
69
features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/WriteDistFilesStorage.kt
Normal file
69
features/files/common/src/jvmMain/kotlin/dev/inmo/postssystem/features/files/common/WriteDistFilesStorage.kt
Normal file
@@ -0,0 +1,69 @@
|
||||
package dev.inmo.postssystem.features.files.common
|
||||
|
||||
import com.benasher44.uuid.uuid4
|
||||
import dev.inmo.postssystem.features.files.common.storage.WriteFilesStorage
|
||||
import dev.inmo.micro_utils.repos.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import java.io.File
|
||||
|
||||
class WriteDistFilesStorage(
|
||||
private val filesFolder: File,
|
||||
private val metasKeyValueRepo: WriteKeyValueRepo<FileId, MetaFileInfo>
|
||||
) : WriteFilesStorage {
|
||||
private val FileId.file
|
||||
get() = File(filesFolder, string)
|
||||
|
||||
private val _deletedObjectsIdsFlow = MutableSharedFlow<FileId>()
|
||||
private val _newObjectsFlow = MutableSharedFlow<FullFileInfoStorageWrapper>()
|
||||
private val _updatedObjectsFlow = MutableSharedFlow<FullFileInfoStorageWrapper>()
|
||||
override val deletedObjectsIdsFlow: Flow<FileId> = _deletedObjectsIdsFlow.asSharedFlow()
|
||||
override val newObjectsFlow: Flow<FullFileInfoStorageWrapper> = _newObjectsFlow.asSharedFlow()
|
||||
override val updatedObjectsFlow: Flow<FullFileInfoStorageWrapper> = _updatedObjectsFlow.asSharedFlow()
|
||||
|
||||
init {
|
||||
if (!filesFolder.exists()) {
|
||||
filesFolder.mkdirs()
|
||||
} else {
|
||||
require(filesFolder.isDirectory) { "$filesFolder must be a directory" }
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun create(values: List<FullFileInfo>): List<FullFileInfoStorageWrapper> = values.map {
|
||||
var newId: FileId
|
||||
var file: File
|
||||
do {
|
||||
newId = FileId(uuid4().toString())
|
||||
file = newId.file
|
||||
} while (file.exists())
|
||||
metasKeyValueRepo.set(newId, it.toMetaFileInfo())
|
||||
file.writeBytes(it.byteArrayAllocator())
|
||||
FullFileInfoStorageWrapper(newId, it)
|
||||
}
|
||||
|
||||
override suspend fun deleteById(ids: List<FileId>) {
|
||||
ids.forEach {
|
||||
if (it.file.delete()) {
|
||||
metasKeyValueRepo.unset(it)
|
||||
_deletedObjectsIdsFlow.emit(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun update(
|
||||
id: FileId,
|
||||
value: FullFileInfo
|
||||
): FullFileInfoStorageWrapper? = id.file.takeIf { it.exists() } ?.writeBytes(value.byteArrayAllocator()) ?.let {
|
||||
val result = FullFileInfoStorageWrapper(id, value.copy())
|
||||
|
||||
metasKeyValueRepo.set(id, value.toMetaFileInfo())
|
||||
_updatedObjectsFlow.emit(result)
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
override suspend fun update(
|
||||
values: List<UpdatedValuePair<FileId, FullFileInfo>>
|
||||
): List<FullFileInfoStorageWrapper> = values.mapNotNull { (id, file) ->
|
||||
update(id, file)
|
||||
}
|
||||
}
|
1
features/files/common/src/main/AndroidManifest.xml
Normal file
1
features/files/common/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1 @@
|
||||
<manifest package="dev.inmo.postssystem.features.files.common"/>
|
Reference in New Issue
Block a user