mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-07 07:53:33 +00:00
* Remove relay * restructure p2p * wip * cleanup webrtc * split up P2P docs * wip * more wip * the fork has moved * finish local network discovery * Document the relay system * be less stupid * a * remote ip from deploy script * remove debug from deploy script * Explain relay setup and usage * Physical pain * fix * error handling for relay setup * Listeners Relay state + merge it into NLM state * `node_remote_identity` * redo libraries hook * toggle relay active in settings * Dedicated network settings page * Stablise P2P debug page * warning for rspc remote * Linear links in docs * fix p2p settings switches * fix typescript errors on general page * fix ipv6 listener status * discovery method in UI * Remove p2p debug menu on the sidebar * wip * lol * wat * fix * another attempt at fixing library hook * fix * Remove sync from sidebar * fix load library code * I hate this * Detect connections over the relay * fix * fixes * a * fix mDNS * a bunch o fixes * a bunch of state management fixes * Metadata sync on connection * skill issue * fix markdown * Clippy cleanup * Backport #2380 * Update interface/locales/en/common.json Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/local-network-discovery.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/local-network-discovery.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/relay.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/relay.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/relay.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/relay.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/relay.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/sd_p2p.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/sd_p2p.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/sd_p2p_proto.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/overview.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/overview.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/relay.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/sd_p2p_proto.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/sd_p2p_proto.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/transport-layer.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/sd_p2p_proto.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/local-network-discovery.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * Update docs/developers/p2p/sd_p2p_proto.mdx Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com> * a * Cleaning binario section * cleanup Docker message * idk * Idempotent listeners * Manual peers working???? * minor fixes * crazy idea - don't panic in the event loop * fixes * debug * debug * LAN badge in network settings * Use `dns_lookup` instead of `tokio::net::lookup_host` * fix * bruh sandwich * proper dialing * a * remove logs * fix * Small cleanup * manual peers state on connected device * a * Fix manual discovery state + give it a badge * Clippy improvements * flip discovery priority * Add `addrs` to debug query * connection candidates in debug * Fix state * Clippppppppppppy * Manual discovery badge * Flesh out ping example * Usage guide * `sd_p2p_proto` examples * More discovery docs * More docs work * docs docs docs and more docs * PONG * rename --------- Co-authored-by: Matthew Yung <117509016+myung03@users.noreply.github.com>
690 lines
18 KiB
Plaintext
690 lines
18 KiB
Plaintext
datasource db {
|
|
provider = "sqlite"
|
|
url = "file:dev.db"
|
|
}
|
|
|
|
generator client {
|
|
provider = "cargo prisma"
|
|
output = "../../crates/prisma/src/prisma"
|
|
module_path = "prisma"
|
|
client_format = "folder"
|
|
}
|
|
|
|
generator sync {
|
|
provider = "cargo prisma-sync"
|
|
output = "../../crates/prisma/src/prisma_sync"
|
|
client_format = "folder"
|
|
}
|
|
|
|
/// @local
|
|
model CRDTOperation {
|
|
id Int @id @default(autoincrement())
|
|
|
|
timestamp BigInt
|
|
model Int
|
|
|
|
record_id Bytes
|
|
// Enum: ??
|
|
kind String
|
|
data Bytes
|
|
|
|
instance_id Int
|
|
instance Instance @relation(fields: [instance_id], references: [id])
|
|
|
|
@@map("crdt_operation")
|
|
}
|
|
|
|
/// @local
|
|
model CloudCRDTOperation {
|
|
id Int @id @default(autoincrement())
|
|
|
|
timestamp BigInt
|
|
model Int
|
|
|
|
record_id Bytes
|
|
// Enum: ??
|
|
kind String
|
|
data Bytes
|
|
|
|
instance_id Int
|
|
instance Instance @relation(fields: [instance_id], references: [id])
|
|
|
|
@@map("cloud_crdt_operation")
|
|
}
|
|
|
|
/// @deprecated: This model has to exist solely for backwards compatibility.
|
|
/// @local
|
|
model Node {
|
|
id Int @id @default(autoincrement())
|
|
pub_id Bytes @unique
|
|
name String
|
|
// Enum: sd_core::node::Platform
|
|
platform Int
|
|
date_created DateTime
|
|
identity Bytes? // TODO: Change to required field in future
|
|
|
|
@@map("node")
|
|
}
|
|
|
|
// represents a single `.db` file (SQLite DB) that is paired to the current library.
|
|
// A `LibraryInstance` is always owned by a single `Node` but it's possible for that node to change (or two to be owned by a single node).
|
|
/// @local
|
|
model Instance {
|
|
id Int @id @default(autoincrement()) // This is is NOT globally unique
|
|
pub_id Bytes @unique // This UUID is meaningless and exists soley cause the `uhlc::ID` must be 16-bit. Really this should be derived from the `identity` field.
|
|
// Enum: sd_p2p::Identity (or sd_core::p2p::IdentityOrRemoteIdentity in early versions)
|
|
identity Bytes?
|
|
// Enum: sd_core::node::RemoteIdentity
|
|
remote_identity Bytes
|
|
|
|
// Enum: uuid::Uuid
|
|
node_id Bytes
|
|
// Enum: sd_core::node::RemoteIdentity
|
|
node_remote_identity Bytes? // TODO: This should not be optional
|
|
metadata Bytes? // TODO: This should not be optional
|
|
|
|
last_seen DateTime // Time core started for owner, last P2P message for P2P node
|
|
date_created DateTime
|
|
|
|
// clock timestamp for sync
|
|
timestamp BigInt?
|
|
|
|
locations Location[]
|
|
CRDTOperation CRDTOperation[]
|
|
CloudCRDTOperation CloudCRDTOperation[]
|
|
|
|
@@map("instance")
|
|
}
|
|
|
|
/// @local
|
|
model Statistics {
|
|
id Int @id @default(autoincrement())
|
|
date_captured DateTime @default(now())
|
|
total_object_count Int @default(0)
|
|
library_db_size String @default("0")
|
|
// local calulations
|
|
total_local_bytes_used String @default("0")
|
|
total_local_bytes_capacity String @default("0")
|
|
total_local_bytes_free String @default("0")
|
|
// library calculations
|
|
total_library_bytes String @default("0")
|
|
total_library_unique_bytes String @default("0")
|
|
total_library_preview_media_bytes String @default("0")
|
|
|
|
@@map("statistics")
|
|
}
|
|
|
|
/// @local
|
|
model Volume {
|
|
id Int @id @default(autoincrement())
|
|
name String
|
|
mount_point String
|
|
total_bytes_capacity String @default("0")
|
|
total_bytes_available String @default("0")
|
|
disk_type String?
|
|
filesystem String?
|
|
is_system Boolean @default(false)
|
|
date_modified DateTime @default(now())
|
|
|
|
@@unique([mount_point, name])
|
|
@@map("volume")
|
|
}
|
|
|
|
/// @shared(id: pub_id, modelId: 1)
|
|
model Location {
|
|
id Int @id @default(autoincrement())
|
|
pub_id Bytes @unique
|
|
|
|
name String?
|
|
path String?
|
|
total_capacity Int?
|
|
available_capacity Int?
|
|
size_in_bytes Bytes?
|
|
is_archived Boolean?
|
|
generate_preview_media Boolean?
|
|
sync_preview_media Boolean?
|
|
hidden Boolean?
|
|
date_created DateTime?
|
|
|
|
scan_state Int @default(0) // Enum: sd_core::location::ScanState
|
|
|
|
/// @local
|
|
// this is just a client side cache which is annoying but oh well (@brendan)
|
|
instance_id Int?
|
|
instance Instance? @relation(fields: [instance_id], references: [id], onDelete: SetNull)
|
|
|
|
file_paths FilePath[]
|
|
indexer_rules IndexerRulesInLocation[]
|
|
|
|
@@map("location")
|
|
}
|
|
|
|
/// @shared(id: pub_id, modelId: 2)
|
|
model FilePath {
|
|
id Int @id @default(autoincrement())
|
|
pub_id Bytes @unique
|
|
|
|
is_dir Boolean?
|
|
|
|
// content addressable storage id - blake3 sampled checksum
|
|
cas_id String?
|
|
// full byte contents digested into blake3 checksum
|
|
integrity_checksum String?
|
|
|
|
// location that owns this path
|
|
location_id Int?
|
|
location Location? @relation(fields: [location_id], references: [id], onDelete: SetNull)
|
|
|
|
// the path of the file relative to its location
|
|
materialized_path String?
|
|
|
|
// the name and extension, MUST have 'COLLATE NOCASE' in migration
|
|
name String?
|
|
extension String?
|
|
hidden Boolean?
|
|
|
|
size_in_bytes String? // deprecated
|
|
size_in_bytes_bytes Bytes?
|
|
|
|
inode Bytes? // This is actually an unsigned 64 bit integer, but we don't have this type in SQLite
|
|
|
|
// the unique Object for this file path
|
|
object_id Int?
|
|
object Object? @relation(fields: [object_id], references: [id], onDelete: SetNull)
|
|
|
|
key_id Int? // replacement for encryption
|
|
// permissions String?
|
|
|
|
date_created DateTime?
|
|
date_modified DateTime?
|
|
date_indexed DateTime?
|
|
|
|
// key Key? @relation(fields: [key_id], references: [id])
|
|
|
|
@@unique([location_id, materialized_path, name, extension])
|
|
@@unique([location_id, inode])
|
|
@@index([location_id])
|
|
@@index([location_id, materialized_path])
|
|
@@map("file_path")
|
|
}
|
|
|
|
/// @shared(id: pub_id, modelId: 3)
|
|
model Object {
|
|
id Int @id @default(autoincrement())
|
|
pub_id Bytes @unique
|
|
// Enum: sd_file_ext::kind::ObjectKind
|
|
kind Int?
|
|
|
|
key_id Int?
|
|
// handy ways to mark an object
|
|
hidden Boolean?
|
|
favorite Boolean?
|
|
important Boolean?
|
|
// if we have generated preview media for this object on at least one Node
|
|
// commented out for now by @brendonovich since they they're irrelevant to the sync system
|
|
// has_thumbnail Boolean?
|
|
// has_thumbstrip Boolean?
|
|
// has_video_preview Boolean?
|
|
// TODO: change above to:
|
|
// has_generated_thumbnail Boolean @default(false)
|
|
// has_generated_thumbstrip Boolean @default(false)
|
|
// has_generated_video_preview Boolean @default(false)
|
|
// integration with ipfs
|
|
// ipfs_id String?
|
|
// plain text note
|
|
note String?
|
|
// the original known creation date of this object
|
|
date_created DateTime?
|
|
date_accessed DateTime?
|
|
|
|
tags TagOnObject[]
|
|
labels LabelOnObject[]
|
|
albums ObjectInAlbum[]
|
|
spaces ObjectInSpace[]
|
|
file_paths FilePath[]
|
|
// comments Comment[]
|
|
exif_data ExifData?
|
|
ffmpeg_data FfmpegData?
|
|
|
|
// key Key? @relation(fields: [key_id], references: [id])
|
|
|
|
@@map("object")
|
|
}
|
|
|
|
// // keys allow us to know exactly which files can be decrypted with a given key
|
|
// // they can be "mounted" to a client, and then used to decrypt files automatically
|
|
// /// @shared(id: uuid)
|
|
// model Key {
|
|
// id Int @id @default(autoincrement())
|
|
// // uuid to identify the key
|
|
// uuid String @unique
|
|
// version String
|
|
// key_type String
|
|
// // the name that the user sets
|
|
// name String?
|
|
// // is this key the default for encryption?
|
|
// // was not tagged as unique as i'm not too sure if PCR will handle it
|
|
// // can always be tagged as unique, the keys API will need updating to use `find_unique()`
|
|
// default Boolean @default(false)
|
|
// // nullable if concealed for security
|
|
// date_created DateTime? @default(now())
|
|
// // encryption algorithm used to encrypt the key
|
|
// algorithm String
|
|
// // hashing algorithm used for hashing the key with the content salt
|
|
// hashing_algorithm String
|
|
// // salt used for encrypting data with this key
|
|
// content_salt Bytes
|
|
// // the *encrypted* master key (48 bytes)
|
|
// master_key Bytes
|
|
// // the nonce used for encrypting the master key
|
|
// master_key_nonce Bytes
|
|
// // the nonce used for encrypting the key
|
|
// key_nonce Bytes
|
|
// // the *encrypted* key
|
|
// key Bytes
|
|
// // the salt used for deriving the KEK (used for encrypting the master key) from the root key
|
|
// salt Bytes
|
|
|
|
// automount Boolean @default(false)
|
|
|
|
// objects Object[]
|
|
// file_paths FilePath[]
|
|
|
|
// @@map("key")
|
|
// }
|
|
|
|
/// @shared(id: object, modelId: 4)
|
|
model ExifData {
|
|
id Int @id @default(autoincrement())
|
|
|
|
resolution Bytes?
|
|
media_date Bytes?
|
|
media_location Bytes?
|
|
camera_data Bytes?
|
|
artist String?
|
|
description String?
|
|
copyright String?
|
|
exif_version String?
|
|
|
|
// purely for sorting/ordering, never sent to the frontend as they'd be useless
|
|
// these are also usually one-way, and not reversible
|
|
// (e.g. we can't get `MediaDate::Utc(2023-09-26T22:04:37+01:00)` from `1695758677` as we don't store the TZ)
|
|
epoch_time BigInt? // time since unix epoch
|
|
|
|
object_id Int @unique
|
|
object Object @relation(fields: [object_id], references: [id], onDelete: Cascade)
|
|
|
|
@@map("exif_data")
|
|
}
|
|
|
|
model FfmpegData {
|
|
id Int @id @default(autoincrement())
|
|
|
|
// Internal FFmpeg properties
|
|
formats String
|
|
bit_rate Bytes // Actually a i64 in the backend
|
|
duration Bytes? // Actually a i64 in the backend
|
|
start_time Bytes? // Actually a i64 in the backend
|
|
|
|
chapters FfmpegMediaChapter[]
|
|
programs FfmpegMediaProgram[]
|
|
|
|
// Metadata for search
|
|
title String?
|
|
creation_time DateTime?
|
|
date DateTime?
|
|
album_artist String?
|
|
disc String?
|
|
track String?
|
|
album String?
|
|
artist String?
|
|
metadata Bytes?
|
|
|
|
object Object @relation(fields: [object_id], references: [id], onDelete: Cascade)
|
|
object_id Int @unique
|
|
|
|
@@map("ffmpeg_data")
|
|
}
|
|
|
|
model FfmpegMediaChapter {
|
|
chapter_id Int
|
|
|
|
start Bytes // Actually a i64 in the backend
|
|
end Bytes // Actually a i64 in the backend
|
|
|
|
time_base_den Int
|
|
time_base_num Int
|
|
|
|
// Metadata for search
|
|
title String?
|
|
metadata Bytes?
|
|
|
|
ffmpeg_data FfmpegData @relation(fields: [ffmpeg_data_id], references: [id], onDelete: Cascade)
|
|
ffmpeg_data_id Int
|
|
|
|
@@id(name: "likeId", [ffmpeg_data_id, chapter_id])
|
|
@@map("ffmpeg_media_chapter")
|
|
}
|
|
|
|
model FfmpegMediaProgram {
|
|
program_id Int
|
|
|
|
streams FfmpegMediaStream[]
|
|
|
|
// Metadata for search
|
|
name String?
|
|
metadata Bytes?
|
|
|
|
ffmpeg_data FfmpegData @relation(fields: [ffmpeg_data_id], references: [id], onDelete: Cascade)
|
|
ffmpeg_data_id Int
|
|
|
|
@@id(name: "likeId", [ffmpeg_data_id, program_id])
|
|
@@map("ffmpeg_media_program")
|
|
}
|
|
|
|
model FfmpegMediaStream {
|
|
stream_id Int
|
|
|
|
name String?
|
|
codec FfmpegMediaCodec?
|
|
aspect_ratio_num Int
|
|
aspect_ratio_den Int
|
|
frames_per_second_num Int
|
|
frames_per_second_den Int
|
|
time_base_real_den Int
|
|
time_base_real_num Int
|
|
dispositions String?
|
|
|
|
// Metadata for search
|
|
title String?
|
|
encoder String?
|
|
language String?
|
|
duration Bytes? // Actually a i64 in the backend
|
|
metadata Bytes?
|
|
|
|
program FfmpegMediaProgram @relation(fields: [ffmpeg_data_id, program_id], references: [ffmpeg_data_id, program_id], onDelete: Cascade)
|
|
program_id Int
|
|
ffmpeg_data_id Int
|
|
|
|
@@id(name: "likeId", [ffmpeg_data_id, program_id, stream_id])
|
|
@@map("ffmpeg_media_stream")
|
|
}
|
|
|
|
model FfmpegMediaCodec {
|
|
id Int @id @default(autoincrement())
|
|
|
|
kind String?
|
|
sub_kind String?
|
|
tag String?
|
|
name String?
|
|
profile String?
|
|
bit_rate Int
|
|
|
|
video_props FfmpegMediaVideoProps?
|
|
audio_props FfmpegMediaAudioProps?
|
|
|
|
stream FfmpegMediaStream @relation(fields: [ffmpeg_data_id, program_id, stream_id], references: [ffmpeg_data_id, program_id, stream_id], onDelete: Cascade)
|
|
stream_id Int
|
|
program_id Int
|
|
ffmpeg_data_id Int
|
|
|
|
@@unique([ffmpeg_data_id, program_id, stream_id])
|
|
@@map("ffmpeg_media_codec")
|
|
}
|
|
|
|
model FfmpegMediaVideoProps {
|
|
id Int @id @default(autoincrement())
|
|
|
|
pixel_format String?
|
|
color_range String?
|
|
bits_per_channel Int?
|
|
color_space String?
|
|
color_primaries String?
|
|
color_transfer String?
|
|
field_order String?
|
|
chroma_location String?
|
|
width Int
|
|
height Int
|
|
aspect_ratio_num Int?
|
|
aspect_ratio_Den Int?
|
|
properties String?
|
|
|
|
codec FfmpegMediaCodec @relation(fields: [codec_id], references: [id], onDelete: Cascade)
|
|
codec_id Int @unique
|
|
|
|
@@map("ffmpeg_media_video_props")
|
|
}
|
|
|
|
model FfmpegMediaAudioProps {
|
|
id Int @id @default(autoincrement())
|
|
|
|
delay Int
|
|
padding Int
|
|
sample_rate Int?
|
|
sample_format String?
|
|
bit_per_sample Int?
|
|
channel_layout String?
|
|
|
|
codec FfmpegMediaCodec @relation(fields: [codec_id], references: [id], onDelete: Cascade)
|
|
codec_id Int @unique
|
|
|
|
@@map("ffmpeg_media_audio_props")
|
|
}
|
|
|
|
//// Tag ////
|
|
|
|
/// @shared(id: pub_id, modelId: 5)
|
|
model Tag {
|
|
id Int @id @default(autoincrement())
|
|
pub_id Bytes @unique
|
|
name String?
|
|
color String?
|
|
|
|
is_hidden Boolean? // user hidden entire tag
|
|
|
|
date_created DateTime?
|
|
date_modified DateTime?
|
|
|
|
tag_objects TagOnObject[]
|
|
|
|
@@map("tag")
|
|
}
|
|
|
|
/// @relation(item: object, group: tag, modelId: 6)
|
|
model TagOnObject {
|
|
object_id Int
|
|
object Object @relation(fields: [object_id], references: [id], onDelete: Restrict)
|
|
|
|
tag_id Int
|
|
tag Tag @relation(fields: [tag_id], references: [id], onDelete: Restrict)
|
|
|
|
date_created DateTime?
|
|
|
|
@@id([tag_id, object_id])
|
|
@@map("tag_on_object")
|
|
}
|
|
|
|
//// Label ////
|
|
|
|
/// @shared(id: name, modelId: 7)
|
|
model Label {
|
|
id Int @id @default(autoincrement())
|
|
name String @unique
|
|
date_created DateTime?
|
|
date_modified DateTime?
|
|
|
|
label_objects LabelOnObject[]
|
|
|
|
@@map("label")
|
|
}
|
|
|
|
/// @relation(item: object, group: label, modelId: 8)
|
|
model LabelOnObject {
|
|
date_created DateTime @default(now())
|
|
|
|
object_id Int
|
|
object Object @relation(fields: [object_id], references: [id], onDelete: Restrict)
|
|
|
|
label_id Int
|
|
label Label @relation(fields: [label_id], references: [id], onDelete: Restrict)
|
|
|
|
@@id([label_id, object_id])
|
|
@@map("label_on_object")
|
|
}
|
|
|
|
//// Space ////
|
|
|
|
model Space {
|
|
id Int @id @default(autoincrement())
|
|
pub_id Bytes @unique
|
|
name String?
|
|
description String?
|
|
date_created DateTime?
|
|
date_modified DateTime?
|
|
|
|
objects ObjectInSpace[]
|
|
|
|
@@map("space")
|
|
}
|
|
|
|
model ObjectInSpace {
|
|
space_id Int
|
|
space Space @relation(fields: [space_id], references: [id], onDelete: Restrict)
|
|
|
|
object_id Int
|
|
object Object @relation(fields: [object_id], references: [id], onDelete: Restrict)
|
|
|
|
@@id([space_id, object_id])
|
|
@@map("object_in_space")
|
|
}
|
|
|
|
//// Job ////
|
|
|
|
model Job {
|
|
id Bytes @id
|
|
|
|
name String?
|
|
action String? // Will be composed of "{action_description}(-{children_order})*"
|
|
|
|
// Enum: sd_core::job::job_manager:JobStatus
|
|
status Int? // 0 = Queued
|
|
|
|
// List of errors, separated by "\n\n" in case of failed jobs or completed with errors
|
|
errors_text String? // Deprecated, use `critical_error` or `non_critical_errors` instead
|
|
critical_error String? // Serialized error field with info about the failed job after completion
|
|
non_critical_errors Bytes? // Serialized non-critical errors field with info about the completed job with errors after completion
|
|
|
|
data Bytes? // Deprecated
|
|
metadata Bytes? // Serialized metadata field with info about the job after completion
|
|
|
|
parent_id Bytes?
|
|
|
|
task_count Int?
|
|
completed_task_count Int?
|
|
date_estimated_completion DateTime? // Estimated timestamp that the job will be complete at
|
|
|
|
date_created DateTime?
|
|
date_started DateTime? // Started execution
|
|
date_completed DateTime? // Finished execution
|
|
|
|
parent Job? @relation("jobs_dependency", fields: [parent_id], references: [id], onDelete: SetNull)
|
|
children Job[] @relation("jobs_dependency")
|
|
|
|
@@map("job")
|
|
}
|
|
|
|
//// Album ////
|
|
|
|
model Album {
|
|
id Int @id
|
|
pub_id Bytes @unique
|
|
name String?
|
|
is_hidden Boolean?
|
|
|
|
date_created DateTime?
|
|
date_modified DateTime?
|
|
|
|
objects ObjectInAlbum[]
|
|
|
|
@@map("album")
|
|
}
|
|
|
|
model ObjectInAlbum {
|
|
date_created DateTime?
|
|
album_id Int
|
|
album Album @relation(fields: [album_id], references: [id], onDelete: NoAction)
|
|
|
|
object_id Int
|
|
object Object @relation(fields: [object_id], references: [id], onDelete: NoAction)
|
|
|
|
@@id([album_id, object_id])
|
|
@@map("object_in_album")
|
|
}
|
|
|
|
//// Indexer Rules ////
|
|
|
|
model IndexerRule {
|
|
id Int @id @default(autoincrement())
|
|
pub_id Bytes @unique
|
|
|
|
name String? @unique
|
|
default Boolean?
|
|
rules_per_kind Bytes?
|
|
date_created DateTime?
|
|
date_modified DateTime?
|
|
|
|
locations IndexerRulesInLocation[]
|
|
|
|
@@map("indexer_rule")
|
|
}
|
|
|
|
model IndexerRulesInLocation {
|
|
location_id Int
|
|
location Location @relation(fields: [location_id], references: [id], onDelete: Restrict)
|
|
|
|
indexer_rule_id Int
|
|
indexer_rule IndexerRule @relation(fields: [indexer_rule_id], references: [id], onDelete: Restrict)
|
|
|
|
@@id([location_id, indexer_rule_id])
|
|
@@map("indexer_rule_in_location")
|
|
}
|
|
|
|
/// @shared(id: key, modelId: 9)
|
|
model Preference {
|
|
key String @id
|
|
value Bytes?
|
|
|
|
@@map("preference")
|
|
}
|
|
|
|
model Notification {
|
|
id Int @id @default(autoincrement())
|
|
read Boolean @default(false)
|
|
// Enum: crate::api::notifications::NotificationData
|
|
data Bytes
|
|
expires_at DateTime?
|
|
|
|
@@map("notification")
|
|
}
|
|
|
|
/// @shared(id: pub_id, modelId: 10)
|
|
model SavedSearch {
|
|
id Int @id @default(autoincrement())
|
|
pub_id Bytes @unique
|
|
|
|
// enum: crate::api::search::saved::SearchTarget
|
|
target String?
|
|
search String?
|
|
filters String?
|
|
|
|
name String?
|
|
icon String?
|
|
description String?
|
|
// order Int? // Add this line to include ordering
|
|
|
|
date_created DateTime?
|
|
date_modified DateTime?
|
|
|
|
@@map("saved_search")
|
|
}
|